Skip to content

Instantly share code, notes, and snippets.

@expede
Last active March 18, 2018 01:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save expede/a8047d3f139985682f9a42ce3ed0013b to your computer and use it in GitHub Desktop.
Save expede/a8047d3f139985682f9a42ce3ed0013b to your computer and use it in GitHub Desktop.
Interactive Elixir (1.6.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> use Witchcraft
iex(2)> alias Algae.Maybe
# With a Just
iex(5)> monad %Maybe.Just{} do
...(5)> a <- Maybe.Just.new(1)
...(5)> b <- Maybe.Just.new(2)
...(5)> return(a + b)
...(5)> end
%Algae.Maybe.Just{just: 3}
# Same with Nothing
iex(6)> monad %Maybe.Nothing{} do
...(6)> a <- Maybe.Just.new(1)
...(6)> b <- Maybe.Just.new(2)
...(6)> return(a + b)
...(6)> end
%Algae.Maybe.Just{just: 3}
# Makes no difference if there's something in the Just
iex(5)> monad %Maybe.Just{just: 42} do
...(5)> a <- Maybe.Just.new(1)
...(5)> b <- Maybe.Just.new(2)
...(5)> return(a + b)
...(5)> end
%Algae.Maybe.Just{just: 3}
# Because of how Nothing short circuits, we skip the return function
iex(7)> monad 12.3456 do # floats are not monads
...(7)> a <- Maybe.Just.new(1)
...(7)> b <- Maybe.Nothing.new()
...(7)> return(a + b)
...(7)> end
%Algae.Maybe.Nothing{}
# `Monad.return/1` is just `Applicative.of/1`, ie: partially applied `of/2` with whatever we hand to the `monad` macro.
# There is no type environment carried around in Elixir, so `Monad %Sample{} do` is a way of emulating type metadata for the `return`
#
# Strictly speaking, all this gets you the ability to:
# 1. Write pure-yet-imperative-feeling code, because `return` is familiar
# 2. Use `return` in several places without needing to always specify the context that you're in
# The example above but using more `return`:
iex(8)> monad %Maybe.Nothing{} do
...(8)> a <- return(1)
...(8)> b <- return(2)
...(8)> return(a + b)
...(8)> end
%Algae.Maybe.Just{just: 3}
# This code is far more general (and thus portable) than the one with explicit values on each line.
#For example:
iex(10)> context_add =
...(10)> fn(sample) ->
...(10)> monad sample do
...(10)> a <- return(1)
...(10)> b <- return(2)
...(10)> return(a + b)
...(10)> end
...(10)> end
#Function<6.99386804/1 in :erl_eval.expr/5>
iex(11)> context_add.([])
[3]
iex(12)> context_add.(["these", "values", "are", "thrown out"])
[3]
iex(13)> context_add.(%Algae.Either.Right{})
%Algae.Either.Right{right: 3}
iex(14)> context_add.(%Algae.Maybe.Nothing{})
%Algae.Maybe.Just{just: 3}
iex(15)> context_add.(%Algae.Tree.Rose{})
%Algae.Tree.Rose{forest: [], rose: 3}
# Obviously that's a somewhat silly example, but it should help illustrate the behaviour :)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment