owned this note
owned this note
Published
Linked with GitHub
# Type-safe, type-level, type-driven solutions with PureScript - Justin Woo 大會筆記
{%hackmd D_yXRZ3kQuiR5RjV0P_kPg %}
> 請等待大會開始
###### tags: `#FEDC2018`
Speaker: Justin Woo(禹)
## What this talk is
- Talk generally about what PureScript is
- Talk about interesting things from PureScript missing from most languages
- Show you how the computer can do repetitive and error-prone things for you with just type definitions
- Hopefully get you excited to learn more about PureScript
## What is PureScript?
- A language similar to Haskell that compiles to JS
- Unlike annotation-based languages, Types are first class
- Gives you tools to encode more information in your codebase
- A culture of “sky’s the limit”
## Make invalid states impossible
- This isn’t a binary property, and some languages don’t give you enough power
- In reality, a spectrum of how much you choose to encode at this time
- Type alias: least safety, greatest convenience
- Newtype: where constructors are exported or not, for explicit identification
- Refinements: where constructor should not be exported, where structural subtypes of validations can be required
## What is a "#Type" aka. row type of Type?
Think about records:
- Statically defined fields with static label names
- Heterogeneous, where each field can have different type
- But each field will always be the correct Type
But `{ fields... }` syntax is just sugar for records which are parameterized by this row type
## Make invalid states impossible, part 2
Think cardinality: is it valid to have independent fields, or is it a sum type?
Is it actually a homogeneous Map or is it actually a Record?
Quick check: if you ever want Map of a sum type key or value but you already know what keys you have, it's almost always a record
> Type aren't just for checking your work
>
## Decoding JSON should be free
If you have static information available about the type you want, you should be able to derive operations for free
[Simple JSON](https://github.com/justinwoo/purescript-simple-json)
## Type-driven programs
Simple-JSON and many other libraries work by using type classes, which resolve based on concrete contexts
```
class ReadForeign a where readImpl :: Foreign -> F a
instance readString :: ReadForeign String where
instance readArray :: ReadForeign a => ReadForeign (Array a) where instance readMaybe :: ReadForeign a => ReadForeign (Maybe a) where instance readRecord ::
( RowToList fields fieldList, ReadForeignFields fieldList () fields ) => ReadForeign (Record fields)
```
## What is RowToList?
We can work with the static row type information, make it an iterable list at the type level, and match that to instances
```
toRLProxy :: forall row rl. RowToList row rl => Proxy { | row } -> RLProxy rl toRLProxy _ = RLProxy
rlMyJSON :: RLProxy
(Cons "apple" String (Cons "banana" Int (Cons "cherry" (Maybe Boolean)
Nil)))
rlMyJSON = toRLProxy (Proxy :: Proxy MyJSON)
instance [...] ReadForeignFields (Cons name ty tail)
instance [...] ReadForeignFields (Nil)
```
## Other examples of type-driven programs
- We can do a lot of things with this:
- Type-level routing between server endpoints and frontend requests
- Implement a type-safe Cycle.js (drivers -> sources, sinks -> drivers)
- Refinement types (validation in row types, run validation per field)
- Decode INI files
- Diff two differently typed records
- Exhaustively match polymorphic variant members
- And more!
- More and more exciting things are possible with the combination of static type information and “type-level programming”
## Type synthesis with other type information
This type signature is inferred:
```
getEm :: forall a b. AllowedParamType a => AllowedParamType b =>
DBConnection -> { "$name" :: a, "$count" :: b } -> Aff Foreign
getEm db = J.queryDB db queryP
where
queryP = SProxy :: SProxy
"select name, count from mytable where name = $name and count = $count "
```
[Previous talk in Milan](https://speakerdeck.com/justinwoo/superior-string-spaghetti-with-purescript-jajanmen)
## Learn PureScript!
- Various ways to use PureScript
- Small modules that you import in to existing projects (100% interop)
- Hoisting of PureScript in JS or JS in PureScript
- Small applications with existing libraries
- Requires some upfront investment
- Reading, doing some practice problems, looking at core libraries like PureScript-Effect
- Learning about FFI, i.e. `foreign import name :: _ <> exports.name = ...`
- This has immediate payoff: you can write anything for browser/Node after learning this
- Requires some community engagement
- Local usergroups: https://facebook.com/groups/PureScript.tw
- Discourse: https://purescript-users.ml
- `#purescript`, `#purescript-beginners` on FP Chat:fpchat-invite.herokuapp.com
- Ask me anything: twitter.com/jusrin00