[Haskell-cafe] What is <-
Jochem Berndsen
jochem at functor.nl
Sun Aug 8 11:38:17 EDT 2010
michael rice wrote:
> That was my suspicion. So, you can't change horses (monads) in mid-stream.
>
> A parallel question:
>
> main = do ... -- in the IO monad
>
> I know I can have other *do*s in main,
>
> if foo
> then do
> .
> .
> else do
> .
> .
>
> but must all these other *do*s also be in the same IO monad?
Yes, if you write it like that, they have to. Let us take as an example
(in the IO monad):
f = do
x <- getLine
if null x
then y
else z
Desugaring gives:
f =
getLine >>= (\x -> if null x then y else z)
Since getLine :: IO String and (>>=) :: Monad m => m a -> (a -> m b) ->
m b, we see that
m = IO
a = String
So the type of (\x -> if null x then y else z) in the above expression
will be String -> IO b. This means that the parameter x will be of type
String, and "if null x then y else z" will be of type IO b. This implies
that y and z both will be of type IO b. So if you write y and z as a
do-block, this will be in the IO monad.
However, there is no special rule that says "in an expression all
do-blocks must have the same type". E.g., the following is a valid
expression:
do -- in the Maybe monad.
return Nothing
listToMaybe $ do -- in the [] monad.
return 4
What
> determines what monad a *do* is "in"? The first line after the *do*?
Type inference. E.g.
f = do
return []
will be of type Monad m => m [a].
There is nothing special about monads in this regard, only the
"do"-notation is special: it is desugared as described elsewhere in the
thread and in the Report.
HTH, Jochem
--
Jochem Berndsen | jochem at functor.nl
More information about the Haskell-Cafe
mailing list