The definitions of bind
and result
are fine, and do constitute a monad. However, identity
is not a legal function to pass to bind
for your monad. In Haskell, that would not pass the typechecker, because
bind :: (Monad m) => m a -> (a -> m b) -> m b
The second argument here is your f
, in this case identity
. But identity :: a -> a
does not fit with the type required for bind
's f
.
In order to use something "identity-like" in your monad, you need to lift identity
into the monad by composing it with result
. For example,
(let [id (comp result identity)] ;; or (liftm identity), if you have liftm
(bind (bind (result 3) id) id))
returns (result 3)
, ie (fn [] 3)
.
Edit
I did some more thinking about this, since my assertion that a -> a
is an incompatible type with a -> m b
is clearly not quite right: if you let a
be m b
, the types do match. So it's okay to use identity
as the bind
function in some cases. Specifically, if your original input is (result (result 3))
, you can bind
identity
and get out just (result 3)
. In fact, (bind identity x)
is basically (join x)
! This is not exactly news - I've read it multiple times - but I guess it hadn't sunk in, or I'd have answered this question more correctly to begin with.
Anyway, just thought I'd share this, since it's a bit topical and should flesh out my answer a bit.