Mark Eibes
2020-01-25T15:05:45Z

PurescriptExamples.purs

| module Main (main) where
|
| import Prelude
|
| import Data.Foldable (traverse_)
| import Data.Function.Uncurried (Fn2, runFn2)
| import Data.Maybe (Maybe(..), fromMaybe)
| import Data.String (toUpper)
| import Data.Time.Duration (Milliseconds(..))
| import Effect (Effect)
| import Effect.Aff (Aff, delay)
| import Effect.Class.Console (logShow)
| import Effect.Console (log)
| import Milkis (URL(..), getMethod, text)
| import Milkis as M
| import Milkis.Impl.Node (nodeFetch)
| import Record (insert, merge)
| import Type.Prelude (SProxy(..))
|
| main :: Effect Unit
| main = do
| log "Hi!"
|
| --| Basics
|
| -- A value
| number = 5.0
|
| -- A function
| add number1 number2 = number1 + number2
| alsoAdd = \number1 number2 -> number1 + number
|
| -- Some names are different
| toString = show
| some = Just
| none = Nothing
| getOrElse = fromMaybe
|
| -- but the concepts are the same
| theSame = some(12) == Just 12
| theSameToo = (some(12)#getOrElse(4)) == fromMaybe 4 (Just 12)
|
| -- money is important
| withParentheses = show (Just 4)
| withDollar = show $ Just 4
| withPound = Just 4 # show
|
| -- making some data
| data Mammal = Cat | Dog
|
| -- Pattern matching
| talk mammal = case mammal of
| Cat -> "meow"
| Dog -> "woof"
|
| -- making data with data in it
| data Person = PersonConstructor String Int
| -- making better data with data in it
| newtype Name = NameConstructor String
| -- usually the constructor name is the same as the type
| newtype Age = Age Int
| safeAge age = if age > 0 && age < 120 then Just (Age age) else Nothing
|
| data Person' = Person' Name Age
| -- an alternative with records
| type ReasonablePerson =
| { name :: String
| , age :: Int
| }
| -- or the megasafe version
| newtype FoolproofPerson = FoolproofPerson
| { name :: Name
| , age :: Age
| }
|
| -- create a reasonable person
| rp = { name: "Heinz", age: 58 }
| -- update it
| rpOlder :: ReasonablePerson
| rpOlder = rp { age = rp.age + 1 }
|
| type DetailedPerson =
| { name :: String
| , age :: Int
| , address :: String
| , hobbies :: Array String
| }
|
| detailedPerson :: DetailedPerson
| detailedPerson =
| merge rp { address: "Universe", hobbies: ["PureScript"]}
|
| -- The same is possible with Sum Types (Polymorphic Variants) which is great for error handling
|
| -- Type annotations
| aString :: String
| aString = "A String"
|
| aFunction :: Int -> Int
| aFunction n = n + 2
|
| anotherFunction :: Int -> (Int -> Int)
| anotherFunction n m = n + m
|
| -- Calling JS
| foreign import valueFromJs :: Int
| foreign import functionFromJs :: Int -> Int
| foreign import leftPad :: Int -> String -> String
| -- Alternative for more readable JS
| foreign import leftPadUncurried :: Fn2 Int String String
| leftPad' :: Int -> String -> String
| leftPad' = runFn2 leftPadUncurried
|
| foreign import data MyClass :: Type
| foreign import newMyClass :: MyClass
| foreign import initMyClass :: MyClass -> Effect Unit
|
| -- Effects
| println :: String -> Effect Unit
| println = log
| -- Effect is simply a function with 0 arguments at runtime
| foreign import jsEffect :: Effect Unit
|
| -- Concurrent Effects
| wait :: Milliseconds -> Aff Unit
| wait ms = delay ms
|
| googleSomethingOptimistically :: Aff String
| googleSomethingOptimistically = do
| response <- fetch (URL "https://www.google.com/q=purescript") { method: getMethod }
| text response
|
| -- Advanced
| -- Polymorphic functions
|
| myIdentity :: forall a. a -> a
| myIdentity x = x
|
| -- Typeclass constraints
| toStringAgain :: forall a. Show a => Eq a => a -> String
| toStringAgain = show
|
| -- Row types
| capitaliseName :: forall r. { name :: String | r } -> { name :: String | r }
| capitaliseName record = record { name = toUpper record.name }
|
| screamHeinz = capitaliseName { name: "Heinz" }
| screamOther = capitaliseName { name: "Dembowski", age: 98 }
|
| addAgeToRecord age record = insert (SProxy :: _ "age") age record
| withAge = addAgeToRecord 34 { does: "n't", matter: 4.2 }
| -- exceptIfItAlreadyHasAge = addAgeToRecord 34 { age: 12, matter: 4.2 }
|
| -- Utils
| fetch = M.fetch nodeFetch