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):

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)
:empty

This 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)
11

Maybe exports a set of operators for handling the chaining functions:

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
Link to this function

fold(input, default \\ nil, function)

View Source
@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 Just value and return the value itself;
  • Return the 'default' value given to the function. If no 'default' value is provided, nil is 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

Link to this macro

nothing?(arg1)

View Source (macro)

Checks whether a Maybe monad is Nothing (essentially empty)

example

Example

iex> import WarmFuzzyThing.Maybe iex> nothing?(nil) true iex> nothing?({:ok, 1}) false

@spec on_just(t(value), function) :: t(value)
when value: any(), function: (value -> :ok)

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
Link to this function

on_nothing(maybe, function)

View Source
@spec on_nothing(t(value), function) :: t(value)
when value: any(), function: (() -> :ok)

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
@spec sequence([t(value)]) :: t([value]) when value: any()

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