# Simple/Naive Implementation of Identity and Maybe Monad in Elixir

This is my first crack at a identity monad and a maybe monad in Elixir:

defmodule Monad do
@doc "v is value to be wrapped as monadic value"
def return(v), do: fn -> v end
@doc "m is monad function, mv is monadic value"
def bind(m, mv), do: m.(mv.())
end

id = fn s -> s end
r = Monad.bind(id, h)

maybe = fn s -> if is_nil(s), do: :error, else: s end
r = Monad.bind(maybe, h)


I'd like to see if there is a way to make the monad into a protocol since the return and bind seem to be common to all monads.

I think you're sort of missing the point with this code - the difference between different kinds of monads (Maybe vs. List vs. Identity, etc.) is in the different implementations of return and bind. I think a good starting place might be reading through a library that implements monads in elixir, like monad. Looking into that you can see that for example Maybe is implemented like this (simplifying):

def return(x), do: {:just, x}

def bind({:just, x}, f), do: f.(x)
def bind(:nothing, _), do: :nothing

def fail(_), do: :nothing


While for example Error (the second-simplest I think) is implemented like this:

def return(x), do: {:ok, x}

def bind(e = {:error, _}, _), do: e
def bind({:ok, x}, f), do: f.(x)

def fail(msg), do: {:error, msg}


The difference between the two being that in one case you only get information that there is no result (:nothing) while in the other you either get a result or some information on the error (represented by {:error, _}). Also note that both have additional helper functions to for example extract the result (presumably at the end of the computation).

• I'm trying to follow your comments. You're saying I should make the code less generic? I understand that I might change the return function to get different behavior there but the bind can be easily parameterized by the function which is passed in so I'm not sure I understand how making it less generic is an improvement. – Onorio Catenacci Jul 22 '15 at 11:45
• Again - bind should be implemented differently, depending on the type of monad you are using. The function f passed to bind on the other hand is part of the user's logic. For example find_user |> bind(&authenticate_user/1) |> bind(&render_response/1) - assuming this is the maybe monad you'd expect find_user, authenticate_user, render_response to be functions provided by the user of your monad API and returning {:just, _} or :nothing. – Paweł Obrok Jul 22 '15 at 11:54
• Also check out MonadEx. – rbrown Jul 22 '15 at 14:41