Elm Syntax
Crash Course
Elm is an ML style language, like Haskell.
It can seem a littl strange at first, so here's a crash course
Functions
add x y = x + y
add 10 11 -- 21
add' = (\x y -> x + y) -- anonymous function
Pattern Matching
or b1 b2 =
case b1 of
True -> True
False -> b2
Let...In
f x =
let
double = x * 2
in
double + double
let allows us to assign names to values, or define functions in a limited scope
Lists
xs = [1, 2, 3]
4::xs -- [4, 1, 2, 3]
head xs
case xs of
x::xs -> Just x
[] -> Nothing
Tuples
t = (1, "Foo")
t' = (2, "Bar", [1, 2, 3])
Union Types
type Action =
Add
| Sub
calc action n m =
case action of
Add -> n + m
Sub -> n - m
calc Add 1 2 -- 3
calc Sub 5 3 -- 2
Unions are like enums in other languages, but have more power as we'll see later
Union Types
With Values
type Action =
Increment
| Decrement
type Counter = Counter Int
step action (Counter n)=
case action of
Increment -> Counter (n + 1)
Decrement -> Counter (n - 1)
step Increment (Counter 1) -- Counter 2
step Decrement (Counter 2) -- Counter 1
This example is fairly trivial, but the point is that each value of a type can carry data
The point is they can hold any data
Polymorphic Unions
type Maybe a =
Just a
| Nothing
type Either a b =
Left a
| Right b
types can carry data with them, and we can parameterize that data
Here 'a' is a type variable
Maybe a isn't a "concrete" type, it's a like a function waiting for an argument
Maybe Int & Maybe Char are concrete types
Records
Defining & Accessing
person = { first = "Jane", last = "Smith" }
person.first -- "Jane"
.last person -- "Smith"
List.map .last people -- a list of last names
sayHi { first } =
"Hi " ++ first
sayHi person -- "Hi Jane"
Records are like objects / hashes in other languages
But records in Elm are far more powerful than, say, objects in JS
They are also very similar to n-tuples or a sum type containing various values
Records, however, come with accessors (which are just functions), provide a more familiar interface
Records
Updating
{ person - first } -- removes a field
{ person | age = 20 } -- adds a new field & value
{ person | first <- "John" } -- updates a field
{ person - last | surname = "Smith" }
-- combine adding & deleting to rename a field
Important note here, this is not mutation, data is immutable.
Each operation creates a new record, using the source as a template
Types
The Part Where Everyone Stops Listening
The idea of a statically typed languages turns a lot of people off
But notice that none of the previous examples have type annotations
Yet each expression has a type and is statically checked at compile time
Elms type inference sorts all of that out
You don't NEED to annotate your code, but you should.
Types can help guide an implmentation, and they provide documentation
Examples of Types
5 : number
4.5 : Float
"Hi" : String
'c' : Char
Keyboard.presses : Signal Int
person : {first : String, last : String}
add : Int -> Int -> Int
map : (a -> b) -> List a -> List b
Numbers in Elm can be a float or an int, but Elm also includes the broader 'number'
number is a type that could be a Float or an Int depending on the usage
Signals play a HUGE role in Elm. Unfortunately, the topic is too large to get into now
The type of a function is a list of argument types, separated by '->'
The final type in the signature is the return type
Polymorphic functions look like regular functions, except types are replaced by type variables
The type variable 'a' will stand for the same type throughout the signature
'a' and 'b' CAN be different types, but are not required to be