Background
I am trying to up my Functional Programming (FP) skills and one of the things that newcomers first learn in FP is the Option
Type (aka, Maybe Monad).
Option what?
This construct is present in many languages, Haskell has Maybe and Java and Python (yes, Python!) have Optional.
Basically this type models a value that may or may not be there.
How it all comes down to Elixir
Most FP languages have comprehensions, Scala and Elixir have the for
construct while Haskell has its famous do
notation.
In Scala and Haskell, these comprehensions work not only with Enumerables (such as Lists) but also with our Option
type (which is not an enumerable).
I mention this, because according to my understanding, Elixir’s comprehensions only works on Enumerables. Furthermore, as far as I know, there is not Option
type datastructure in Elixir.
What does Elixir have?
Elixir has tagged tuples in the form of {:ok, val}
or {:error, reason}
. Now while Elixir comprehensions can pattern match with tagged tuples:
iex> values = [good: 1, good: 2, bad: 3, good: 4]
iex> for {:good, n} <- values, do: n * n
[1, 4, 16]
It also ignores values that do not pattern match:
iex> values = [good: 1, good: 2, bad: 3, good: 4]
iex> for {:bananas, n} <- values, do: n * n
[]
However, this does not replicate the behaviour of the Option
type correctly. Following is an example in Scala:
for {
validName <- validateName(name)
validEnd <- validateEnd(end)
validStart <- validateStart(start, end)
} yield Event(validName, validStart, validEnd)
Having in mind this signatures:
def validateName(name: String): Option[String]
def validateEnd(end: Int): Option[Int]
def validateStart(start: Int, end: Int): Option[Int]
The result of the full comprehension expression, should any function return None
, will be None
.
With Elixir, the bad result would be ignored and the pipeline would simply continue happily ever after.
Questions
At this point I am thinking that implement this Option
type as a structure that implements the Enumerable
Protocol (so it can be used in Elixir comprehensions) is something that should be possible.
However, I am not sure I want to go down that route if I can simulate similar behavior using tuples.
So I have the following questions:
- Is it possible to simulate the
Option
type using tagged tuples inside Elixir comprehensions? - Are there any Elixir libraries in the wild that have Monadic types (like the one we saw here) usable within Elixir comprehensions? (I know about witchcraft but they have their own construct for comprehensions, which for the time being, I think is a little overkill. I am interesting in something that works with Elixir’s native comprehension functionality).