From 199e2e8726fd913b4accc9e94c386c0cb26fb447 Mon Sep 17 00:00:00 2001 From: Fredrik Dyrkell Date: Sun, 31 Aug 2014 23:26:56 +0200 Subject: [PATCH] Learn Purescript in Y minutes --- purescript.html.markdown | 195 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 purescript.html.markdown diff --git a/purescript.html.markdown b/purescript.html.markdown new file mode 100644 index 00000000..6bff7545 --- /dev/null +++ b/purescript.html.markdown @@ -0,0 +1,195 @@ +--- +language: purescript +contributors: + - ["Fredrik Dyrkell", "http://www.lexicallyscoped.com"] +--- + +PureScript is a small strongly, statically typed language compiling to Javascript. + +* Learn more at [http://www.purescript.org/](http://www.purescript.org/) +* Documentation: [http://docs.purescript.org/en/latest/](http://docs.purescript.org/en/latest/) +* Book: Purescript by Example, [https://leanpub.com/purescript/](https://leanpub.com/purescript/) + +```haskell + +-- +-- 1. Primitive datatypes that corresponds to their Javascript +-- equivalents at runtime. + +-- Numbers +1 + 7*5 :: Number -- 36 +-- Types are inferred, so the following works fine +9 / 2.5 + 4.4 -- 8 +-- Hexadecimal literals +0xff + 1 -- 256 +-- Unary negation +6 * -3 -- -18 +6 * negate 3 -- -18 +-- Modulus +3 % 2 -- 1 +4 % 2 -- 0 +-- Inspect the type of an expression in psci +:t 9 / 2.5 + 4.4 -- Prim.Number + +-- Booleans +true :: Boolean -- true +false :: Boolean -- false +-- Negation +not true --false +23 == 23 -- true +1 /= 4 -- true +1 >= 4 -- false +-- Comparisions < <= > >= +-- are defined in terms of compare +compare 1 2 -- LT +compare 2 2 -- EQ +compare 3 2 -- GT +-- Conjunction and Disjunction +true && (9 >= 19 || 1 < 2) -- true + +-- Strings +"Hellow" :: String -- "Hellow" +-- Multiline string +"Hellow\ +\orld" -- "Helloworld" +-- Concatenate +"such " ++ "amaze" -- "such amaze" + +-- +-- 2. Arrays are Javascript arrays, but must be homogeneous + +[1,1,2,3,5,8] :: [Number] -- [1,1,2,3,5,8] +[true, true, false] :: [Boolean] -- [true,true,false] +-- [1,2, true, "false"] won't work +-- `Cannot unify Prim.Number with Prim.Boolean` +-- Cons (prepend) +1 : [2,4,3] -- [1,2,4,3] + +-- Requires purescript-arrays (Data.Array) +-- and purescript-maybe (Data.Maybe) + +-- Safe access return Maybe a +head [1,2,3] -- Just (1) +tail [3,2,1] -- Just ([2,1]) +init [1,2,3] -- Just ([1,2]) +last [3,2,1] -- Just (1) +-- Random access - indexing +[3,4,5,6,7] !! 2 -- Just (5) +-- Range +1..5 -- [1,2,3,4,5] +length [2,2,2] -- 3 +drop 3 [5,4,3,2,1] -- [2,1] +take 3 [5,4,3,2,1] -- [5,4,3] +append [1,2,3] [4,5,6] -- [1,2,3,4,5,6] + +-- +-- 3. Records are Javascript objects, with zero or more fields, which +-- can have different types +let book = {title: "Foucault's pendulum", author: "Umberto Eco"} +-- Access properties +book.title -- "Foucault's pendulum" + +getTitle b = b.title +-- Works on all records with a title (but doesn't require any other field) +getTitle book -- "Foucault's pendulum" +getTitle {title: "Weekend in Monaco", artist: "The Rippingtons"} -- "Weekend in Monaco" +-- Update a record +changeTitle b t = b {title = t} +changeTitle book "Ill nome della rosa" -- {title: "Ill nome della + -- rosa", author: "Umberto Eco"} + +-- +-- 4. Functions +sumOfSquares x y = x*x+y*y +sumOfSquares 3 4 -- 25 +-- In psci you have to write `let` in front of the function to get a +-- top level binding +mod x y = x % y +mod 3 2 -- 1 +-- Infix application of function +3 `mod` 2 -- 1 + +-- function application have higher precedence than all other +-- operators +sumOfSquares 3 4 * sumOfSquares 4 5 -- 1025 + +-- Conditional +abs' n = if n>=0 then n else -n +abs' (-3) -- 3 + +-- Guarded equations +abs n | n >= 0 = n + | otherwise = -n + +-- Pattern matching + +-- Note the type signature, input is an array of numbers The pattern +-- matching destructures and binds the array into parts +first :: [Number] -> Number +first (x:_) = x +first [3,4,5] -- 3 +second :: [Number] -> Number +second (_:y:_) = y +second [3,4,5] -- 4 +sumTwo :: [Number] -> [Number] +sumTwo (x:y:rest) = (x+y) : rest +sumTwo [2,3,4,5,6] -- [5,4,5,6] + +-- sumTwo doesn't handle when the array is empty or just have one +-- element in which case you get an error +sumTwo [1] -- Failed pattern match + +-- Complementing patterns to match +-- Good ol' Fibonacci +fib 1 = 1 +fib 2 = 2 +fib x = fib (x-1) + fib (x-2) +fib 10 -- 89 + +-- Use underscore to match any, where you don't care about the binding name +isZero 0 = true +isZero _ = false + +-- Pattern matching on records +ecoTitle {author = "Umberto Eco", title = t} = Just t +ecoTitle _ = Nothing + +ecoTitle book -- Just ("Foucault's pendulum") +ecoTitle {title: "The Quantum Thief", author: "Hannu Rajaniemi"} -- Nothing +-- ecoTitle requires both field to type check: +ecoTitle {title: "The Quantum Thief"} -- Object does not have property author + +-- Lambda expressions +(\x -> x*x) 3 -- 9 +(\x y -> x*x + y*y) 4 5 -- 41 +sqr = \x -> x*x + +-- Currying +add x y = x + y -- is equivalent with +add = \x -> (\y -> x+y) +add3 = add 3 +:t add3 -- Prim.Number -> Prim.Number + +-- Forward and backward function composition +-- drop 3 followed by taking 5 +(drop 3 >>> take 5) (1..20) -- [4,5,6,7,8] +-- take 5 followed by dropping 3 +(drop 3 <<< take 5) (1..20) -- [4,5] + +-- Operations using higher order functions +even x = x % 2 == 0 +filter even (1..10) -- [2,4,6,8,10] +map (\x -> x+11) (1..5) -- [12,13,14,15,16] + +-- Requires purescript-foldable-traversabe (Data.Foldable) + +foldr (+) 0 (1..10) -- 55 +sum (1..10) -- 55 +product (1..10) -- 3628800 + +-- Testing with predicate +any even [1,2,3] -- true +all even [1,2,3] -- false + +``` +