Assume I have a function (plusOne
in the example below) that only accepts and returns an Int
. But I don't have an Int
; instead, I have a Maybe Int
; and if this Maybe Int
contains a value then I want to pass it to plusOne
and get a Just
of whatever plusOne
returns, or if its rather a Nothing
then I want this Nothing
to propagate.
In such a case we have liftM
to code this in an elegant way:
import Control.Monad
plusOne :: Int -> Int
plusOne n =
n+1 -- a very complicated computation that is failsafe
main =
let n = Just 15 -- a very complicated computation that can fail
in let res = liftM plusOne n
in print res
So far so good. But, can something like this be done with constructors as well?
Forget about plusOne
. Now I have: data SomeData = SomeData Int
and want to obtain a Maybe (SomeData Int)
from my Maybe Int
. The solution seems noticeably less elegant:
import Control.Monad
data SomeData = SomeData Int
deriving Show -- so that print works
main =
let n = Just 15
in let res = n >>= (\nn -> Just (SomeData nn))
-- alternatively: in let res = liftM (\nn -> SomeData nn) n
in print res
Both solutions above (with >>=
or with liftM
) require going through an anonymous lambda function which, to my intuition, shouldn't be necessary and only serves to clobber the code. Is there a way to avoid it? Can I somehow "lift" the someData
constructor just as I could lift plusOne
in the first snippet?
You can simply use function composition:
main =
let n = Just 15
res = n >>= Just . SomeData
in print res
although as Robin Zigmond points out, you can simply use fmap
, since fmap f x
is equivalent to x >>= return . f
, and return == Just
for the Maybe
monad.
main = let n = Just 15
res = fmap SomeData n -- or SomeData <$> n
in print res
Moral of the story: don't use a monad where all you need is a functor.