Types • Type classes with functional dependencies • Tooling with purescript-ide server + client • Docs for packages on Pursuit • Easy-to-use build tool in Pulp • Typed holes with type-directed search • No runtime -- compiles to real JS • Row types • ...and more!
◦ Key is Symbol (a type-level string kind) ◦ Value is of the kind provided to the row data Record :: # Type -> Type -- takes row of Type to define a Type type Person = { name :: String, age :: Number } type Person = Record (name :: String, age :: Number) • Eff works this way! kind Effect data HTTP :: Effect data Eff :: # Effect -> Type -> Type main :: Eff ( http :: HTTP ) Unit
could use these rows as lists of fields? Wouldn’t that be fun? kind RowList data Nil :: RowList data Cons :: Symbol -> Type -> RowList -> RowList type PersonRow = (name :: String, age :: Number) type PersonRowList = (Cons "name" String (Cons "age" Number Nil))
and work with things on the type level? Type classes! ◦ Using instances for each branch • Simple example: getting keys from a record class Keys (xs :: RowList) where keysImpl :: RLProxy xs -> List String instance nilKeys :: Keys Nil where keysImpl _ = mempty -- Phantom types reminder data Maybe a = Nothing | Just a data Proxy a = Proxy data RLProxy (xs :: RowList) = RLProxy
RowList 2. Reflect the Symbol to a string value 3. Get the rest by calling keysImpl on the tail 4. Cons this string onto the rest of the keys That’s it! instance consKeys :: ( IsSymbol name , Keys tail ) => Keys (Cons name ty tail) where keysImpl _ = first : rest where first = reflectSymbol (SProxy :: SProxy name) rest = keysImpl (RLProxy :: RLProxy tail)
a class for RowList, but this needs to work for row types from Records • RowToList allows us to convert row to RowList for exactly this! keys :: forall row rl. RowToList row rl => Keys rl => Record row -> List String keys _ = keysImpl (RLProxy :: RLProxy rl) • Since we have everything from the type level, the record ends up being a glorified Proxy
◦ Also writes JSON safely (e.g. no function stringifying) • Purescript-Kancho: restrict Purescript types to Elm port types and generate Elm types • Purescript-OhYes: restrict Purescript types to be Typescript-safe and generate type definitions, using polymorphic variants through Purescript-Variant to support discriminant-field union types in Typescript • Purescript-ChocoPie: a Cycle.js-like library that exposes record-based APIs for creating cycles of Events from Purescript-Behaviors • Purescript-IndexedDB-Safe by Antti Holvikari: type-safe wrappers for IndexedDB • … and more! Other applications of RowList
start using] Purescript?” • Writing type-level code using RowList? ◦ Not really, but sometimes ◦ And you will learn these from usage • Defining your own type classes and working with them? ◦ Not necessarily, but sometimes ◦ And you will learn these from usage • Understanding how to use constraints and throw them around? ◦ Yes and no ◦ You will learn these from usage ◦ You can always start with the most concrete types and use more general ones over time ▪ e.g. Monoid mempty vs []