Why does a monad use “return” or “unit” rather than “lift”?
https://softwareengineering.stackexchange.com/questions/231136
-
02-10-2020 - |
Question
This is partly genuine curiosity, and partly a check on my understanding. I'm probably missing the point.
In Haskell, why does a monad use operations called return
or unit
to describe putting a type into the container -- lifting it into the monadic space? It seems more intuitive to call the operation lift
.
Right now, in my (probably incorrect) port of monads into my own project, I'm using (pseudocode):
MyThing.lift(x).bind(f)...
rather than
MyThing.unit(x).bind(f)...
because it's more intuitive for me to think of lifting x into the monadic space.
Is that wrong-headed? I keep getting burned by not thinking abstractly enough, and I suspect that's the case again.
Solution
The term unit
comes from category theory where we define a monad as two natural transformations unit : Identity ~> m
and join : m x m ~> m
. In case you're curious, bind f = join . fmap f
.
return
comes from do notation where return
looks appropriately algol-ish. It's actually debatable whether this was a good name since it tends to suggest that return
is some sort of control flow instead of just being a plain old function.
We usually reserve lift
for things that are more like a functor and lift whole functions or monads. lift :: m a -> t m a
and liftM :: (a -> b) -> m a -> m b
.
OTHER TIPS
As Benjamin Hodgson mentioned in his comment, the term lift is usually applied to lifting non-monadic functions into the monad.
As for why the function is specifically called return
, that is because it is used in the do
syntactic sugar, which is meant to resemble an imperative C/ALGOL style code block, which typically used the return
keyword to return a value.
Similarly, bind
is called SelectMany
in .NET, because its monad comprehensions are meant to resemble SQL queries.