View Source WarmFuzzyThing.Maybe (WarmFuzzyThing v0.1.0)
The Maybe monad is a union between two general notions: Just and Nothing (the naming is inherited from Haskell and it depicts the idea: "Maybe I have a value, maybe I don't.").
This means that a Maybe monad can either be a Just or it can be a Nothing (think of it as a simple union between two types).
A Just is represented by the well known success type tuple {:ok, value} when value: any(),
where as a Nothing is represented by nil, since it's the closest Elixir gets to representing "nothing".
Maybe exports a set of function for ease of chaining functions (transformations):
WarmFuzzyThing.Maybe.fmap/2- Used for applying a function over the value of aMaybemonad;WarmFuzzyThing.Maybe.bind/2- Used for applying a function over a value inside aMaybemonad that returns a brand newMaybemonad;WarmFuzzyThing.Maybe.fold/3- Used for either returning a default value or applying a function over the value inside theMaybemonad;
example
Example
iex> WarmFuzzyThing.Maybe.fmap({:ok, 1}, fn v -> v + 1 end)
{:ok, 2}
iex> WarmFuzzyThing.Maybe.fmap(nil, fn v -> v + 1 end)
nil
iex> WarmFuzzyThing.Maybe.bind({:ok, 1}, fn v -> {:ok, v + 1} end)
{:ok, 2}
iex> WarmFuzzyThing.Maybe.bind(nil, fn v -> {:ok, v + 1} end)
nil
iex> WarmFuzzyThing.Maybe.bind({:ok, 1}, fn v -> nil end)
nil
iex> WarmFuzzyThing.Maybe.fold({:ok, 1}, &WarmFuzzyThing.id/1)
1
iex> WarmFuzzyThing.Maybe.fold(nil, &WarmFuzzyThing.id/1)
nil
iex> WarmFuzzyThing.Maybe.fold(nil, :empty, &WarmFuzzyThing.id/1)
:emptyThis set of function are setup in a way to allow for easy pipelining.
example-1
Example
iex> {:ok, "hello"}
...> |> WarmFuzzyThing.Maybe.fmap(fn v -> v <> " world" end)
...> |> WarmFuzzyThing.Maybe.fmap(&String.length/1)
...> |> WarmFuzzyThing.Maybe.bind(fn
...> v when v <= 20 -> {:ok, v}
...> _ -> nil
...> end)
...> |> WarmFuzzyThing.Maybe.fold(&WarmFuzzyThing.id/1)
11Maybe exports a set of operators for handling the chaining functions:
~>representsWarmFuzzyThing.Maybe.fmap/2~>>representsWarmFuzzyThing.Maybe.bind/2<~>representsWarmFuzzyThing.Maybe.fold/3
example-2
Example
iex> import WarmFuzzyThing.Maybe, only: [~>: 2, ~>>: 2, <~>: 2]
iex> {:ok, "elixir"} ~> &String.length/1
{:ok, 6}
iex> nil ~> &String.length/1
nil
iex> {:ok, "elixir"} ~>> &({:ok, String.length(&1)})
{:ok, 6}
iex> {:ok, ""} ~>> fn "" -> nil; v -> {:ok, String.length(v)} end
nil
iex> {:ok, "elixir"} <~> &String.length/1
6
iex> nil ~>> fn v -> {:ok, v + 1} end
nil
iex> nil <~> fn v -> v + 1 end
nil
iex> nil <~> {:not_found, fn v -> v + 1 end}
:not_found
iex> {:ok, "elixir"}
...> ~> fn v -> v <> " with monads" end
...> ~> fn v -> v <> " is awesome" end
...> ~>> fn v when v < 20 -> nil; v -> {:ok, String.length(v)} end
...> <~> {0, &WarmFuzzyThing.id/1}
29
Link to this section Summary
Functions
Operator for handling WarmFuzzyThing.Maybe.fold/3.
Apply a function over the Just portion of a Maybe monad.
The result of the function will be a brand new Maybe monad.
This means that the value inside the monad can change from Just to Nothing and vice versa.
Apply a function over the Just portion of a Maybe monad.
The result of the function will be the new Just portion of the Maybe WarmFuzzyThing.
Depending of the value inside the Maybe monad, fold will either (no pun intended)
Checks whether a Maybe monad is a Just
Checks whether a Maybe monad is Nothing (essentially empty)
Call a 'void' type of function if the Maybe monad is a Just.
WarmFuzzyThing.Maybe.on_just/2 returns the Maybe as is. No changes are applied.
Call a 'void' type of function if the Maybe monad is a Nothing.
WarmFuzzyThing.Maybe.on_nothing/2 returns the Maybe as is. No changes are applied.
Cycles through a sequence of Maybes, if it finds an empty Maybe it short circuits
and returns an "empty" Maybe.
Operator for handling WarmFuzzyThing.Maybe.fmap/2.
Operator for handling WarmFuzzyThing.Maybe.bind/2.
Link to this section Types
@type t(value) :: nil | {:ok, value}
Link to this section Functions
@spec t(value) <~> ({default :: new_value, function} | function) :: new_value when value: any(), function: (value -> new_value), new_value: any()
Operator for handling WarmFuzzyThing.Maybe.fold/3.
example
Example
iex> import WarmFuzzyThing.Maybe, only: [<~>: 2]
iex> {:ok, 1} <~> fn v -> v + 1 end
2
iex> {:ok, "hello"} <~> fn _v -> "world" end
"world"
iex> {:ok, "hello"} <~> &String.length/1
5
iex> nil <~> fn v -> v + 1 end
nil
iex> nil <~> {:not_found, fn v -> v + 1 end}
:not_found
@spec bind(t(value), function) :: new_maybe when value: any(), function: (value -> new_maybe), new_maybe: t(new_value), new_value: any()
Apply a function over the Just portion of a Maybe monad.
The result of the function will be a brand new Maybe monad.
This means that the value inside the monad can change from Just to Nothing and vice versa.
If a Maybe monad with a Nothing value is passed, the function is not invoked,
WarmFuzzyThing.Maybe.bind/2 return a nil.
example
Example
iex> WarmFuzzyThing.Maybe.bind({:ok, 1}, fn v -> {:ok, v + 1} end)
{:ok, 2}
iex> WarmFuzzyThing.Maybe.bind({:ok, "hello"}, fn _v -> {:ok, "world"} end)
{:ok, "world"}
iex> WarmFuzzyThing.Maybe.bind({:ok, "hello"}, &({:ok, String.length(&1)}))
{:ok, 5}
iex> WarmFuzzyThing.Maybe.bind({:ok, "hello"}, fn _v -> nil end)
nil
iex> WarmFuzzyThing.Maybe.bind(nil, fn v -> v + 1 end)
nil
@spec fmap(t(value), function) :: t(new_value) when value: any(), function: (value -> new_value), new_value: any()
Apply a function over the Just portion of a Maybe monad.
The result of the function will be the new Just portion of the Maybe WarmFuzzyThing.
If a Maybe monad with a Nothing value is passed, the function is not invoked,
WarmFuzzyThing.Maybe.fmap/2 return a nil.
example
Example
iex> WarmFuzzyThing.Maybe.fmap({:ok, 1}, fn v -> v + 1 end)
{:ok, 2}
iex> WarmFuzzyThing.Maybe.fmap({:ok, "hello"}, fn _v -> "world" end)
{:ok, "world"}
iex> WarmFuzzyThing.Maybe.fmap({:ok, "hello"}, &String.length/1)
{:ok, 5}
iex> WarmFuzzyThing.Maybe.fmap(nil, fn v -> v + 1 end)
nil
@spec fold(t(value), default :: new_value, function) :: new_value when value: any(), function: (value -> new_value), new_value: any()
Depending of the value inside the Maybe monad, fold will either (no pun intended):
- Apply the given function over the
Justvalue and return the value itself; - Return the
'default'value given to the function. If no'default'value is provided,nilis returned;
example
Example
iex> WarmFuzzyThing.Maybe.fold({:ok, 1}, fn v -> v + 1 end)
2
iex> WarmFuzzyThing.Maybe.fold({:ok, "hello"}, fn _v -> "world" end)
"world"
iex> WarmFuzzyThing.Maybe.fold({:ok, "hello"}, &String.length/1)
5
iex> WarmFuzzyThing.Maybe.fold(nil, fn v -> v + 1 end)
nil
iex> WarmFuzzyThing.Maybe.fold(nil, :not_found, fn v -> v + 1 end)
:not_found
iex> WarmFuzzyThing.Maybe.sequence([])
{:ok, []}
Checks whether a Maybe monad is a Just
example
Example
iex> import WarmFuzzyThing.Maybe iex> just?({:ok, 1}) true iex> just?(nil) false
Checks whether a Maybe monad is Nothing (essentially empty)
example
Example
iex> import WarmFuzzyThing.Maybe iex> nothing?(nil) true iex> nothing?({:ok, 1}) false
Call a 'void' type of function if the Maybe monad is a Just.
WarmFuzzyThing.Maybe.on_just/2 returns the Maybe as is. No changes are applied.
If the Maybe has a Nothing value inside, the function is not invoked.
example
Example
iex> WarmFuzzyThing.Maybe.on_just({:ok, 1}, &IO.inspect/1)
1
{:ok, 1}
iex> WarmFuzzyThing.Maybe.on_just(nil, &IO.inspect/1)
nil
Call a 'void' type of function if the Maybe monad is a Nothing.
WarmFuzzyThing.Maybe.on_nothing/2 returns the Maybe as is. No changes are applied.
If the Maybe has a 'right' value inside, the function is not invoked.
example
Example
iex> WarmFuzzyThing.Maybe.on_nothing({:ok, 1}, &IO.inspect/1)
{:ok, 1}
iex> WarmFuzzyThing.Maybe.on_nothing(nil, fn -> IO.inspect("Empty maybe monad") end)
"Empty maybe monad"
nil
Cycles through a sequence of Maybes, if it finds an empty Maybe it short circuits
and returns an "empty" Maybe.
Otherwise returns a Maybe with a list of all values.
example
Example
iex> WarmFuzzyThing.Maybe.sequence([{:ok, 1}, {:ok, 2}])
{:ok, [1, 2]}
iex> WarmFuzzyThing.Maybe.sequence([])
{:ok, []}
iex> WarmFuzzyThing.Maybe.sequence([{:ok, 1}, nil, {:ok, 2}])
nil
iex> WarmFuzzyThing.Maybe.sequence([nil])
nil
@spec t(value) ~> function :: t(new_value) when value: any(), function: (value -> new_value), new_value: any()
Operator for handling WarmFuzzyThing.Maybe.fmap/2.
example
Example
iex> import WarmFuzzyThing.Maybe, only: [~>: 2]
iex> {:ok, 1} ~> fn v -> v + 1 end
{:ok, 2}
iex> {:ok, "hello"} ~> fn _v -> "world" end
{:ok, "world"}
iex> {:ok, "hello"} ~> &String.length/1
{:ok, 5}
iex> nil ~> fn v -> v + 1 end
nil
@spec t(value) ~>> function :: new_maybe when value: any(), function: (value -> new_maybe), new_maybe: t(new_value), new_value: any()
Operator for handling WarmFuzzyThing.Maybe.bind/2.
example
Example
iex> import WarmFuzzyThing.Maybe, only: [~>>: 2]
iex> {:ok, 1} ~>> fn v -> {:ok, v + 1} end
{:ok, 2}
iex> {:ok, "hello"} ~>> fn _v -> {:ok, "world"} end
{:ok, "world"}
iex> {:ok, "hello"} ~>> &({:ok, String.length(&1)})
{:ok, 5}
iex> {:ok, "hello"} ~>> fn _v -> nil end
nil
iex> nil ~>> fn v -> {:ok, v + 1} end
nil