November 21, 2019
elm is a good intro for Functional Programming. It's simple. The language only has a small set of functional features compared with other full-featured language like Haskell.
For Functional Programmers, you might feel it's not enough, but for Functional Programming beginners, I think it's a great starting point to learn.
In this article I will not cover about the web aspect of elm, it will be about the programming language it self.
As a FP beginner, I wanted to share with some simple example what tool and libraries were useful to write functional code.
First simple example is
fold. I think most of the people is familiar with it, since it's becoming a defacto-standard in many programming languages.
List.map will apply a function to every element of list.
This is a type definition:
map : (a -> b) -> List a -> List b
It will take a function that gets
a and return
b, takes a list of element
a as a second parameter, and finally returns list of
List.map (\a -> a * 2) [1, 2, 4] -- [2, 4, 8]
You can use the pipe operator
|> to make it look more functional.
This is the type definition and the implementation:
(|>) : a -> (a -> b) -> b --- apR : a -> (a -> b) -> b apR x f = f x
The code can be refactored like this.
[1, 2, 4] |> List.map (\a -> a * 2)
As you may know operators like
* is also a function that has the type definition as follows.
(*) : number -> number -> number
Meaning we can rewrite the function like.
[1, 2, 4] |> List.map (\a -> (*) 2 a)
In the end we can refactor the code like this, since
(*) 2's type is
number -> number, which matches the type of the first parameter of List.map which is
(a -> b) in this case both
b is number.
[1, 2, 4] |> List.map ((*) 2)
This is called point free programming, and one of the fun parts in functional programming.
List.filter filters the elements that satisfy the condition.
This is the type definition.
filter : (a -> Bool) -> List a -> List a
Let's write a simple example of filtering only even numbers
[1, 2, 3, 4, 5] |> List.filter (\a -> modBy 2 a == 0) -- [2, 4]
It's looks nice, it's uses pipes, but can we make it more concise, meaning we make it point free?
Yes we can! By introducing
>> the compose operator.
[1, 2, 3, 4, 5] |> List.filter (modBy 2 >> (==) 0)
Looks super nice! And by leveraging the
|> pipes, you can pipe as many functions and modify the list.
[1, 2, 3, 4, 5] |> List.filter (modBy 2 >> (==) 0) |> List.map ((*) 3)
Last function I want to introduce is the
List.foldr. In some programming language it's also known as
It reduces a list from the left for
List.foldl and right for
The type definition is the same for both function.
(a -> b -> b) -> b -> List a -> b
The first parameter is a function that takes 2 parameters, the first parameter is the element of the list, and the second parameter is the accumulator, meaning it will the output, after iterating the elements.
The second parameter is the initial value of the accumulator.
The most famous example is summing up each elements in a list.
[1, 2, 3, 4] |> List.foldl (\a b -> a + b) 0 -- 10
(+) type definition is
number -> number -> number, which again matches the type definition of the first paramter of
foldl, since the initial value a
By this you can refactor the code something like this:
[1, 2, 3, 4] |> List.foldl (+) 0
Nice and simple 😌
Though we only looked at 3 basic function of a List, there's a quite a few techniques you can use to make the code look more functional by using
>>, and using operators like
(*) in a functional way.
There's a lot more interesting functions in List package in elm, like
Which I'm happy to write and share about it later on.
If you are more interested it's worth taking a look at the core documentation. The code is also enjoyable to read!
Thanks for Reading.