FunLand.Monad (fun_land v0.10.0)

A Monad: a sequence of operations inside a context.

Monads are hard to explain, because they are very powerful but extremely general at the same time.

Simply put: To be a Monad, something has to be Applicative, as well as Chainable (and therefore also be Appliable and Mappable). Therefore, a monad is very versatile, as it allows us to perform all these four operations:

  • new, which allows us to put anything inside a new structure of this kind.
  • map, which allows us to take a normal function transforming one element, and change it into a function that transforms all of the contents of the structure.
  • chain, which allows us to take a function that usually returns a new structure of this kind, and instead apply it on an already-existing structure, the result being a single new structure instead of multiple layers of it.
  • apply_with, which allows us to take a partially-applied function inside a structure of this kind to be applied with another structure of this kind.

This allows us to:

  • Take any normal value and put it into our new structure.
  • Use any normal functions as well as any functions returning a structure of this kind to be used in a sequence of operations.
  • determine what should happen between subsequent operations. (when/how/if the next step should be executed)

Link to this section Summary

Functions

Allows you to write multiple consecutive operations using this monad on new lines. This is called 'monadic do-notation'.

Link to this section Functions

Link to this function

apply_with(a, b)

See FunLand.Appliable.apply_with/2.

See FunLand.Chainable.chain/2.

See FunLand.Mappable.map/2.

Link to this macro

monadic(monad, list)

(macro)

Allows you to write multiple consecutive operations using this monad on new lines. This is called 'monadic do-notation'.

Rules:

  1. Every normal line returns a new instance of the monad.
  2. You can write x <- some_expr_returning_a_monad_instance to bind x to whatever is inside the monad. You can then use x on any subsequent lines.
  3. If you want to use one or multiple statements, use let something = some_statement or let something = do ...

The final line is of course expected to also return an instance of the monad. Use new at any time to new a value back into a monad if you need.

Inside the monadic context, the module of the monad that was defined is automatically imported. Any local calls to e.g. new, apply, chain or functions you've defined yourself in your monad module will thus be called on your module.

Examples

iex> require FunLand.Monad
iex> FunLand.Monad.monadic({:ok, nil}) do
iex>   x <- {:ok, 10}
iex>   y <- {:ok, 20}
iex>   new(x * y)
iex> end
{:ok, 200}

iex> require FunLand.Monad
iex> FunLand.Monad.monadic({:ok, nil}) do
iex>   x <- {:ok, 10}
iex>   y <- {:error, :something_went_wrong}
iex>   new(x * y)
iex> end
{:error, :something_went_wrong}

See FunLand.Applicative.new/2.