Reputation: 530
I am trying to wrap my head around Monads, and feel that if I could get an explaination to why this doesn't compile, I'd have a better understanding.
module Main where
import Data.Maybe
import System.Environment
myFunc :: String-> Maybe String
myFunc x = Just x
main :: IO ()
main = myFunc "yo" >>= putStrLn
The error I get is
blah.hs:9:10:
Couldn't match type `Maybe' with `IO'
Expected type: IO String
Actual type: Maybe String
In the return type of a call of `myFunc'
In the first argument of `(>>=)', namely `myFunc "yo"'
In the expression: myFunc "yo" >>= putStrLn
I realize that the issue is that I'm trying to match a Maybe
with an IO
, but I'm not entire sure how to cast my Maybe'd variable into an IO. Any help would be greatly appreciated!
Upvotes: 2
Views: 4080
Reputation: 4635
Casting Maybe String
to IO
is the same as turning a Maybe String
to anything else: you need to pick a value to map Nothing
to, and a value to map each Just x
to. Since you want to map to IO String
, I assume you want to map Nothing
to an exception and Just x
to return x
:
import Control.Exception
data NoString = NoString deriving (Typeable, Show)
instance Exception NoString
maybeToIO :: Maybe String -> IO String
maybeToIO Nothing = throwIO NoString
maybeToIO (Just x) = return x
main = maybeToIO (myFunc "yo") >>= putStrLn
However, I suspect that, in a real application, you would want to map Nothing
onto defined behavior; maybe printing nothing, for example:
main = case myFunc "yo" of
Nothing -> return ()
Just x -> putStrLn x
Basically, don't get too hung up on the fact that Maybe
and IO
are both monads; the monad operations are just ways of making values of those types; once you've got your Maybe
values, you still need to process them as ordinary data structures (although Haskell does have awesome ways of doing that:
main = maybe (return ()) putStrLn $ myFun "yo"
for example).
Upvotes: 3
Reputation: 48644
You are correct in realizing that you are trying to match a Maybe
with an IO
. For the bind (>>=
) operator to typecheck, both the Monad should be the same. One way to solve this problem would be to wrap the Maybe
in an IO
monad using return
:
return (myFunc "yo") >>= putStrLn . show
Or more simply:
return (myFunc "yo") >>= print
That being said, you don't need all the fancy monad operators here. This should simply work:
main :: IO ()
main = print . myFunc $ "yo"
Upvotes: 8