https://github.com/elm/compiler/tree/main/hints
I found much of the content for this article at: https://sporto.gitbooks.io/elm-tutorial/content/en/01-foundations/02-functions.html
Here’s now to create a learning environment where you can edit a file full of Elm code, and play with the code.
# make a directory and turn it into an Elm project
mkdir elm
cd elm
elm init
# fire up an editor
gedit &
# open up an elm console
elm replAdd the “.” directory to elm.json. This will tell Elm to search for modules in there:
"source-directories": [
"src",
"."
],Next up, make the file Sample.elm, and just keep it open in the editor:
module Sample exposing (..)
add : Int -> Int -> Int
add a b = a + b
mul : Int -> Int -> Int
mul a b = a * b
sub : Int -> Int -> Int
sub a b = a - bThat’s a bunch of function definitions.
Jump back to the Elm REPL in the terminal:
> import Sample exposing (..)
> mul 2 3
6
> sub 1 2
-1
You can type in more function definitions, and they’ll be available when you type them into the REPL.
So, we’ve created functions so we can type out a language that looks like LISP:
> (add 1 2) 3 : Int > (add (mul 2 2) (mul 5 2) ) 14 : Int > mul (add 2 3) (mul 2 2) 20 : Int > add (mul (mul 2 3) 5) <function> : Int -> Int > add (mul (mul 2 3) 5) 100 130 : Int
That second to last call to add returned a function. The function takes one argument. Putting a 100 after it added 30 to the 100.
(add 1) returns a function that takes one argument, and returns a value that’s one added to the argument.
(add 9) returns a function that takes one argument, and returns a value that’s 9 added to the argument.
Elm has some syntax that messes with the ordering, called a pipe. Here’s the pipe in action:
records
|> map getCost
|> filter (isOver 100)
|> sumSo, that makes sense. It’s like Unix pipes. Records piped into map getCost, piped into filter (isOver 100), piped into sum.
In English: all the costs from records, filtered to be over 100, and summed.
The pipe, |>, rearranges the way functions work. These two function calls are the same:
> add 1 2
3 : Int
> 2 |> add 1
3 : Int
What’s going on?
“2 |> add 1” means 2 passed to add 1. What is “add 1”?
(add 1) returns a function that takes a single argument, and adds 1 to it.
The following are all the same ((2 + 3) * (2 * 2)):
> mul (add 2 3) (mul 2 2)
20 : Int
> (mul 2 2) |> mul (add 2 3)
20 : Int
> (2 |> mul 2) |> mul (3 |> add 2)
20 : Int
> 2 |> mul 2 |> mul (3 |> add 2)
20 : Int
You can reformat the last one in the indented pipes layout:
2
|> mul 2
|> mul (3 |> add 2)
Yeah, it doesn’t make anything clearer, but you can try to work out how Elm evaluates the final value, and it will help clarify the pipe |>.
To show what I mean, I’ll highlight (in red) functions that can resolve to a function:
2
|> mul 2
|> mul (3 |> add 2)
Next, we pass values (on the left of the |>) into these functions, and they evaluate to values (in green).
4
|> mul 5
That mul 5 will return a function:
4
|> mul 5
Then, we pass 4 into the function returned by (mul 5) and evaluate.
20
Obviously, there are more appropriate places to use pipe notation, and this isn’t one of them.
This example below, however, is a good use of pipes.
records
|> map getCost
|> filter (isOver 100)
|> sumThat is the same as:
(sum (filter (isOver 100) (map getCost records)))