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