$30 off During Our Annual Pro Sale. View Details »

Real World PureScript

Real World PureScript

This is a workshop I gave at Monadic Party in Poznan. See the source materials here: https://github.com/justinwoo/real-world-purescript-workshop-2019

Justin Woo

June 21, 2019
Tweet

More Decks by Justin Woo

Other Decks in Programming

Transcript

  1. RealWorldPureScript(Day1)
    JustinWoo
    MonadicParty-2019Jun20
    1/21

    View Slide

  2. Plan
    Day1:WhatisPureScript,andhowdothesetypeswork?
    IntroducethePureScriptlanguage,talkaboutsomedetailswithtypes,kinds,typeclasses+functional
    dependencies,andthewhyandhowofrowtypesandrowtypeclasses.

    Day2:HowdowedoFFI,andhowcanweusetypestomakeitbetter?
    IntroduceFFIinPureScript,andvariousapproachestoFFIwithtypes,frombasicopaquedatatypesto
    datatypeswithrowtypeparameters.

    https://github.com/justinwoo/real-world-purescript-workshop-2019
    2/21

    View Slide

  3. PreviewofDay1contents
    Typealiases,newtypes,datatypes
    Functions,patternmatching,guards
    Anonymousrecords
    Typeclasseswithmultipleparametersandfunctionaldependencies
    Kinds,Rowkind
    Recordsasatypewitharowtypeparameter
    Rowtypeclasses
    3/21

    View Slide

  4. Setup
    Youwillneed...
    PureScript0.13.0
    Spago
    Node10.xorhigher
    Installationmethods:
    ViaNix:https://github.com/justinwoo/easy-purescript-nix
    Vianpm:npmi-gpurescriptspago
    Please,makesureyouhavesetnpmprefixtosomethinglike~/.npm:
    #~/.npmrc
    prefix=/home/your-user/.npm
    npmsetprefix~/.npmrc
    4/21

    View Slide

  5. WhatisPureScript?
    aHaskell-likelanguageforworkingwithJavaScript
    alanguageforusingtypesforbothstaticguaranteesandautomaticallyderivedroutines
    astateofmind
    asourceofmemesonTwitter
    "therowtypeslanguage"
    5/21

    View Slide

  6. Helloworld(src/Main.purs)
    Helloworld:
    moduleMainwhere
    --moduleMain(main)where
    importPrelude
    importEffect(Effect)
    importEffect.Console(log)
    main::EffectUnit
    main=do
    log"Hellosailor!"
    >spagorun
    6/21

    View Slide

  7. Types(src/Basics.purs)
    typeStringAlias=String
    stringAliasValue::StringAlias
    stringAliasValue="Hello"
    newtypeURL=MkURLString
    urlValue::URL
    urlValue=MkURL"https://google.com"
    dataURLorCode
    =IsURLString
    |IsCodeString
    urlOrCodeValue::URLorCode
    urlOrCodeValue=IsCode"banana"
    7/21

    View Slide

  8. Functions
    unwrapURL::URL->String
    unwrapURL(MkURLs)=s
    isCode::URLorCode->Boolean
    isCode(IsCode_)=true
    isCode(IsURL_)=false
    isCode'::URLorCode->Boolean
    isCode'x=casexof
    IsCode_->true
    _->false
    isCode''::URLorCode->Boolean
    isCode''x
    |IsCode_<-x=true
    |otherwise=false
    8/21

    View Slide

  9. AnonymousRecords
    UnlikeHaskell:
    typeMyRecord=
    {apple::String
    ,banana::String
    ,kiwi::String
    }
    Moreonthisaftertalkingabouttypes,Types,rowtypes,andkinds.
    9/21

    View Slide

  10. TypeClasses
    (src/TypeClassesAndKinds.purs)
    Givensomeconcretetype,youshouldbeabletomatchsomeinstance,whichmayleadto
    additionaltypesbeingdetermined
    additionalfunctionsbeingdetermined

    classUnwrapta|t->awhere
    unwrap::t->a
    instanceunwrapURLInstance::UnwrapURLStringwhere
    unwrap(MkURLs)=s
    10/21

    View Slide

  11. classRodeoTypesinputoutput|input->output
    instancerodeoIntString::RodeoTypesIntString
    instancerodeoStringBoolean::RodeoTypesStringBoolean
    dataProxys=Proxy
    rodeoTypes::forallinputoutput
    .RodeoTypesinputoutput
    =>Proxyinput->Proxyoutput
    rodeoTypes_=Proxy
    rodeoResult1::ProxyString
    rodeoResult1=rodeoTypes(Proxy::ProxyInt)
    rodeoResult2::Proxy?hole--Hole'hole'hastheinferredtypeBoolean
    rodeoResult2=rodeoTypes(Proxy::ProxyString)
    11/21

    View Slide

  12. Kinds
    Sofar,everythinghashadinferredkinds,typicallyofkindType.
    dataProxy(s::Type)=Proxy
    AllTypeshavevalues,buthowaboutsomethatdon't?e.g.Symbolkind:
    --fromData.Symbol
    dataSProxy(sym::Symbol)=SProxy
    --Informationissimplyusedincompiletime:
    staticStringProxy::SProxy"helloworld"
    staticStringProxy=SProxy
    --fromData.Symbol
    classIsSymbol(sym::Symbol)where
    reflectSymbol::SProxysym->String
    reflectedSymbolValue::String
    reflectedSymbolValue=reflectSymbolstaticStringProxy
    12/21

    View Slide

  13. Arrowkind
    ->takestwoTypesandgivesyouaType.

    typeIntToInt1=Int->Int
    typeArrow=(->)::Type->Type->Type
    typeFromInt=(->)Int::Type->Type
    typeIntToInt2=FromIntInt::Type
    13/21

    View Slide

  14. Rowkind(src/Rows.purs)
    Specialsymbol#,whichcancreatearowofatypeofakind.
    "Row":unorderedcollectionoffieldsbySymbolandassociatedtypeofakind.
    typeEmptyRow=()::#Type
    typeSingleRow=(a::String)::#Type
    typeSymbolRow=(a::"apple")::#Symbol

    Enablesuser-createddatatypes,e.g.polymorphicvariantsasalibrary:purescript-variant
    foreignimportdataVariant::#Type->Type
    14/21

    View Slide

  15. Records
    --fromPrim("builtins")
    dataRecord::#Type->Type
    typeMyRecordA=
    {apple::String
    ,banana::String
    }
    typeMyRecordB=
    Record
    (apple::String
    ,banana::String
    )
    id=identity::MyRecordA->MyRecordB
    fn1::MyRecordA->String
    fn1r=r.apple
    fn1::MyRecordA->MyRecordA
    fn1r=r{apple="no"}
    15/21

    View Slide

  16. Rowtypeclasses
    WhatifwecouldusetherowtypeparameterofRecordandbeabletogetgenerictype-levelinformation?
    --Built-intypeclassesin`Prim.Row`
    classUnion(left::#Type)(right::#Type)(union::#Type)
    |leftright->union
    ,rightunion->left
    ,unionleft->right
    classNub(original::#Type)(nubbed::#Type)
    |original->nubbed
    classLacks(label::Symbol)(row::#Type)
    classCons(label::Symbol)(a::Type)(tail::#Type)(row::#Type)
    |labelatail->row
    ,labelrow->atail
    16/21

    View Slide

  17. PureScript-Record
    purescript-recordisalibrarywhichusesexactlytheseconstraintstoextracttypeinformation.
    get::forallrr'la
    .IsSymboll
    =>Row.Conslar'r
    =>SProxyl->{|r}->a
    get=--...
    result::?hole--Hole'hole'hastheinferredtypeInt
    result=get(SProxy::_"apple"){apple:123}
    insert::forallr1r2la
    .IsSymboll
    =>Lackslr1
    =>Conslar1r2
    =>SProxyl->a->{|r1}->{|r2}
    17/21

    View Slide

  18. ReviewofDay1contents
    Typealiases,newtypes,datatypes
    Functions,patternmatching,guards
    Anonymousrecords
    Typeclasseswithmultipleparametersandfunctionaldependencies
    Kinds,Rowkind
    Recordsasatypewitharowtypeparameter
    Rowtypeclasses
    18/21

    View Slide

  19. Extrareading
    Generics-Rep(DatatypeGenerics)tutorialhttps://purescript-simple-
    json.readthedocs.io/en/latest/generics-rep.html
    AtutorialofhowtouseDatatypeGenericsinPureScript,whichallowyoutoworkwithageneric
    representationoftypeswhicharederivedbythecompiler,sothatyoucanwriteaseriesoftypeclasses
    thatworkforalldatatypesderivingmethodsofgenericrepresentations.

    "TypeclassesandInstancesarePatternMatchingforTypes"https://github.com/justinwoo/my-
    blog-posts/blob/master/posts/2018-04-27-type-classes-and-instances-are-pattern-matching-for-
    types.md
    Ageneralpostabouthowworkinginthetypelevelhasmanyparallelstoworkinginthevaluelevel,with
    discussionofRowToList.
    19/21

    View Slide

  20. Humor
    "FunTypeLevelliteralnumberarithmeticwithInstanceChains"https://github.com/justinwoo/my-
    blog-posts/blob/master/posts/2018-05-27-fun-type-level-literal-number-arithmetic-with-instance-
    chains.md
    classAdd(l::Symbol)(r::Symbol)(o::Symbol)|l->ro
    instancezeroAdd::Add"zero"rr
    elseinstancesuccAdd::
    (Succl'l
    ,Succrr'
    ,Addl'r'o
    )=>Addlro
    "Wedon'tneedPeanoNumbersinPureScript"https://github.com/justinwoo/my-blog-
    posts/blob/master/posts/2018-09-11-we-dont-need-peano-numbers-in-purescript.md
    resultSub2::SProxy"....................................."
    resultSub2=
    T.sub(SProxy::SProxy"...............................................")(SProxy::SProxyT.Ten)
    20/21

    View Slide

  21. Somememes
    https://twitter.com/jusrin00/status/1012327213591605249
    https://twitter.com/jusrin00/status/933428832618545153
    https://twitter.com/jusrin00/status/963892030773579776
    https://twitter.com/jusrin00/status/1082058122393513984
    https://twitter.com/jusrin00/status/1053763021208723456
    https://twitter.com/jusrin00/status/985596999998328832
    https://twitter.com/jusrin00/status/968471589812670465
    https://twitter.com/jusrin00/status/1008330774884601856
    https://twitter.com/jusrin00/status/1132007452810063874
    https://twitter.com/jusrin00/status/1128059526404554752
    https://twitter.com/jusrin00/status/1094190044175159296
    21/21

    View Slide

  22. View Slide