class: center, middle # A Whirlwind Tour Of PureScript Arun Raghavan [@louiswu](https://twitter.com/louiswu) [nilenso.systems](nilenso.systems) --- # But why * Types ftw * Concisely expressive * “Readable” JS * Easy “FFI” * Backend (node) and frontend * Functional --- # Such Functional * Immutability * Functions as first-class citizens * Composition * Higher order * Purity * Totality --- # Primitive Types * `Int` * `Float` * `String` * `Boolean` * `Array a` - `Array Int` - `Array Boolean` * `{ name :: String, age :: Int }` --- # Roll Your Own Types * `type Name = String` * `data Age = Age Int` * `data Person = Person Name Age` * `data Colour = Red | Green | Blue` * `data Maybe a = Nothing | Just a` --- name: simple-functions # Simple Functions ``` inc :: Int -> Int inc a = a + 1 -- inc 4 == 5 mul :: Int -> Int -> Int mul a b = a * b -- mul 3 7 == 21 ``` --- template: simple-functions Compiles to ```javascript var inc = function (a) { return a + 1; }; var mul = function (a) { return function (b) { return a * b; }; }; ``` --- # Functions can be composed ``` myMath :: Int -> Int myMath a = (mul 7) (inc a) -- myMath 6 == 49 ``` -- With the composition operator ``` myMath :: Int -> Int myMath a = (mul 7 <<< inc) a ``` -- Without parentheses ``` myMath :: Int -> Int myMath a = mul 7 <<< inc $ a ``` -- Simplified ``` myMath :: Int -> Int myMath = mul 7 <<< inc ``` --- name: control-flow # Control Flow ``` data Colour = Red | Green | Blue ``` --- template: control-flow if … then … else ``` colourToString :: Colour -> String colourToString c = if colour == Red then "red" else if colour == Green then "green" else "blue" ``` --- template: control-flow case (pattern match) ``` colourToString :: Colour -> String colourToString c = case c of Red -> "red" Green -> "green" Blue -> "blue" ``` -- function argument pattern match ``` colourToString :: Colour -> String colourToString Red = "red" colourToString Green = "green" colourToString Blue = "blue" ``` --- template: control-flow destructuring ``` maybeColourToString :: Maybe Colour -> String maybeColourToString c = case c of Nothing -> "black" Just c -> colourToString c ``` --- # Effects * All the functions we've seen are pure * But life isn't * What about interaction with network, UI, disk, … * Or anything else with side-effects ``` simpleHttpGet :: String -> Effect String log :: String -> Effect Unit ``` --- name: functors # Functors * Give you a way to apply a function on “things” -- * Things like arrays ``` map :: forall a b. (a -> b) -> Array a -> Array b map isEven [1, 2, 3, 4] == [False, True, False, True] ``` -- * Things like Maybes ``` map :: forall a b. (a -> b) -> Maybe a -> Maybe b map inc (Just 1) == Just 2 map inc Nothing == Nothing ``` -- * Any “thing” ``` map :: forall a b. Functor m ⇒ (a -> b) -> m a -> m b ``` --- template: functors * Effects are also a “thing” ``` map :: forall a b. (a -> b) -> Effect a -> Effect b prepend :: String -> String -> String prepend p s = p ++ " " ++ s name :: Effect String name = readLine helloName :: Effect String helloName = map (prepend "hello") name ``` -- or ``` helloName = prepend "hello" <$> name ``` --- # Applicatives * Functors let you apply a single argument function to a “thing” * Applicatives let you string together “things” ``` readInt :: String -> Maybe Int mulMaybe :: Maybe Int mulMaybe = let a = readInt "1" b = readInt "2" c = readInt "a" mul <$> a <*> b <*> c ``` --- # Monads * Monads let you deal with the contents of a “thing” to generate a new “thing” ``` readLine :: String -> Effect String log :: String -> Effect Unit printName :: Effect Unit printName = do firstName <- readLine lastName <- readLine log $ firstName ++ lastName ``` --- # Next * This was quick and likely overwhelming * To get started for real, check out the PureScript Book * Happy to answer questions after --- class: center, middle # Thanks, ♥ --- # Bonus: A Binary Search Tree ``` data BST a = Empty | Node (BST a) a (BST a) instance bstFunctor :: Functor BST where map f Empty = Empty map f (Node l v r) = Node (map f l) (f v) (map f r) insert :: forall a. Ord a => a -> BST a -> BST a insert x Empty = Node Empty x Empty insert x (Node l v r) | x > v = Node l v (insert x r) | x < v = Node (insert x l) v r | otherwise = Node l v r find :: forall a. Ord a => a -> BST a -> Boolean find x Empty = False find x (Node l v r) | x > v = find x r | x < v = find x l | otherwise = True ```