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

3b48c91bf6b6f0bfd0fda50625598656?s=128

Justin Woo

June 21, 2019
Tweet

Transcript

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

  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
  3. PreviewofDay1contents Typealiases,newtypes,datatypes Functions,patternmatching,guards Anonymousrecords Typeclasseswithmultipleparametersandfunctionaldependencies Kinds,Rowkind Recordsasatypewitharowtypeparameter Rowtypeclasses 3/21

  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
  5. WhatisPureScript? aHaskell-likelanguageforworkingwithJavaScript alanguageforusingtypesforbothstaticguaranteesandautomaticallyderivedroutines astateofmind asourceofmemesonTwitter "therowtypeslanguage" 5/21

  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
  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
  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
  9. AnonymousRecords UnlikeHaskell: typeMyRecord= {apple::String ,banana::String ,kiwi::String } Moreonthisaftertalkingabouttypes,Types,rowtypes,andkinds. 9/21

  10. TypeClasses (src/TypeClassesAndKinds.purs) Givensomeconcretetype,youshouldbeabletomatchsomeinstance,whichmayleadto additionaltypesbeingdetermined additionalfunctionsbeingdetermined  classUnwrapta|t->awhere unwrap::t->a instanceunwrapURLInstance::UnwrapURLStringwhere unwrap(MkURLs)=s

    10/21
  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
  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
  13. Arrowkind ->takestwoTypesandgivesyouaType.  typeIntToInt1=Int->Int typeArrow=(->)::Type->Type->Type typeFromInt=(->)Int::Type->Type typeIntToInt2=FromIntInt::Type 13/21

  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

  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
  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
  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
  18. ReviewofDay1contents Typealiases,newtypes,datatypes Functions,patternmatching,guards Anonymousrecords Typeclasseswithmultipleparametersandfunctionaldependencies Kinds,Rowkind Recordsasatypewitharowtypeparameter Rowtypeclasses 18/21

  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
  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
  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
  22. None