Skip to content

Instantly share code, notes, and snippets.

@reiddraper
Created January 14, 2013 22:24
Show Gist options
  • Save reiddraper/4534094 to your computer and use it in GitHub Desktop.
Save reiddraper/4534094 to your computer and use it in GitHub Desktop.

!SLIDE

Monads in Erlang

monads are simple

!SLIDE

a monad is a monoid in the category of endofunctors

!SLIDE

problem?

!SLIDE

monads get a bad wrap from monad tutorials

!SLIDE

a monad is a Burrito

!SLIDE

a computation container

!SLIDE

category theory

!SLIDE

i'll give a concrete definition, in Erlang

!SLIDE

@@@ erlang
-type monad() :: term().

!SLIDE

@@@ erlang
-type list(Something).

!SLIDE

@@@ erlang
-spec return(term()) -> monad().

!SLIDE

@@@ erlang
-spec bind(monad(), fun((term()) -> monad())) -> monad().

!SLIDE

@@@ erlang
-type either() :: {ok, term()} | {error, term()}.

!SLIDE

@@@ erlang
-spec return(term()) -> either().
return(Value) ->
    {ok, Value}.

!SLIDE

@@@ erlang
-spec bind(monad(), fun((term()) -> either())) -> either().
bind({ok, Val}, MonadicFun) ->
    MonadicFun(Val);
bind({error, _Reason}=Error, _MonadicFun) ->
    Error.

!SLIDE

motivation

!SLIDE

@@@ erlang
doThatThing() ->
    case partOne() of
        {ok, Result1} ->
            case partTwo(Result1) of
                {ok, Result2} ->
                    {ok, 'wow_you_followed_this_far?'};
                {error, _Reason2}=Reason2 ->
                    Reason2
            end;
        {error, _Reason1}=Reason1 ->
            Reason1
    end.

!SLIDE

what we really want to say

@@@ erlang
[fun partOne/0, fun partTwo/1].

!SLIDE

@@@ erlang
bind(partOne(), fun partTwo/1).

!SLIDE

we can chain this together

!SLIDE

@@@ erlang
pipe(Monad, Funs) ->
    lists:foldl(flip(fun bind/2), Monad, Funs).

!SLIDE

@@@ erlang
mAddOne(Val) ->
    Val + 1.

mAlwaysError(Val) ->
    {error, Val}.

!SLIDE

@@@ erlang
pipe({ok, 0}, [fun mAddOne/1, fun mAddOne/1, mAddOne/1, fun mAlwaysError/1]).

!SLIDE

polymorphism

!SLIDE

fucking erlang

!SLIDE

modules

!SLIDE

@@@ erlang
ModuleVar:bind(...)
ModuleVar:return(...)

!SLIDE

other monads

!SLIDE

writer monad

!SLIDE

@@@ erlang
return(Val) ->
    {Val, []}.

writer_bind({Val, SideVal}, MonadFun) ->
    {NewVal, NewSideVal} = MonadFun(Val),
    {NewVal, SideVal ++ NewSideVal}.

!SLIDE

questions?


A brief digression, function composition

!SLIDE

Result = g(f(X)).

NOTE: we can reason about this

!SLIDE

Composition is associative

(g ∘ f)(x) = g(f(x)) 

!SLIDE

Let's write comp in Erlang

comp(A, B) ->
    fun(Input) ->
        A(B(Input))
    end.

!SLIDE

Now let's use it,

(comp(fun addOne/1, fun multiplyTwo/1))(5) %% -> 11

!SLIDE

Functions aren't just abstractions, we've generalized them.

!SLIDE

Sometimes we have a domain-specific idea of how to compose data or computation. This is a monad.

!SLIDE

Return the first 'failure', otherwise keep going

!SLIDE

[fun thingOne/1,
 fun thingTwo/1,
 fun thingThree/1].

!SLIDE

But here's what we do

doThatThing() ->
    case partOne() of
        {ok, Result1} ->
            case partTwo(Result1) of
                {ok, Result2} ->
                    {ok, 'wow_you_followed_this_far?'};
                {error, _Reason2}=Reason2 ->
                    Reason2
            end;
        {error, _Reason1}=Reason1 ->
            Reason1
    end.

!SLIDE

In programming, a concrete monad implements the monad 'interface'

bind
return

!SLIDE

bind defines how your data or compuation composes.

!SLIDE

return takes a non-monadic value and places it inside the monad

!SLIDE

For our failure monad, we might define bind like this:

!SLIDE

bind({ok, X}, NextFun) ->
    NextFun(X);
bind({error, _Reason}=Reason, _NextFun) ->
    Reason.

!SLIDE

return(Val) ->
    {ok, Val}.

!SLIDE

There are actually two other monad functions, but they're not as important:

>>
fail

[Note: writer monad for timings?]

@zkessin
Copy link

zkessin commented Jan 15, 2013

Is there a video of the talk anywhere?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment