if-then-else inside a "do"
Bernard James POPE
bjpop@cs.mu.OZ.AU
Wed, 30 Jan 2002 13:59:58 +1100 (EST)
> In the following code, will "other things" be executed or the "return ()"
> will end function f? I guess the answer is yes ("other things" WILL be
> executed anyway), but I'd like to understand why won't the "return ()" be
> the [state change/result produced] created by f.
>
> f :: IO ()
> f = do
> -- lots of things
> if False then doSomething else (return ())
> -- other things
>
> Thanks,
> -- Andre
Hi Andre,
do notation is just sugar for more complicated expression syntax, for
example:
do
x <- boo
foo
y <- ram x
...
unfolds to something like:
boo >>= \x -> (foo >> (ram x >>= \y -> ...))
>>= and >> are just overloaded functions, as is return
So in your example you have:
f = (lots of things) >> if ... >> (other things)
For this to be meaningful the if expression must re-write to something in the
particular monad that you are using, in your case IO. Both branches
of an if statement must have the same type. Presumably "doSomething"
has type IO (). Likewise "return ()" (in this particular context)
has type IO ().
The job of return is not to alter the flow of control (like return in C
for example) it is to lift a value into the monad:
() :: ()
return () :: Monad m => m ()
Your if statement simply rewrites to: return (), and so f becomes:
f = (lots of things) >> return () >> (other things)
You can think of the expression "return ()" as an empty computation.
The role of ">>" is to thread the IO state through "lots of things",
"return ()" and "other things".
It is instructive to look at other instances of Monad to see what the behaviour
of return is. The Maybe type is quite helpful here:
instance Monad Maybe where
Just x >>= k = k x
Nothing >>= k = Nothing
return = Just
fail s = Nothing
So here, "return ()" is simply "Just ()", which makes it clear that return
is lifting the value () into the type Maybe ().
Hope this helps,
Bernie.