Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When do [do x] and [do return x] evaluate differently?

Tags:

haskell

monads

*Main> do 0

0

*Main> do return 0

0

*Main> do (Just 0)

Just 0

*Main> do return (Just 0)

Just 0

*Main> do Nothing

Nothing

*Main> do return Nothing

Nothing

bareDo :: a -> a
bareDo x = do x

doReturn :: Monad m => a -> m a
doReturn x = do return x

Why would do x and do return x evaluate the same, and when would they don't?

I'm trying to understand Monad, it has been enough tutorial and discussion there yet I couldn't figure it out.

That is even an post writing

Don't read the monad tutorials.

So, I guess getting my hand dirty might help.

I really appreciate whoever help me out of here (I mean do and return, not Monad. I know that would take some days).

like image 787
Rahn Avatar asked Sep 26 '16 10:09

Rahn


1 Answers

do on a single expression accomplishes nothing whatsoever: it's just a syntactic herald indicating that you could use action sequencing here (which would require a monad), but if you don't do that then it has just the same effect as wrapping an expression in layers of redundant parentheses.

So your example session is equivalent to this:

Prelude> 0
0
Prelude> return 0
0
Prelude> Just 0
Just 0
Prelude> return (Just 0)
Just 0
Prelude> Nothing
Nothing
Prelude> return Nothing
Nothing

Now the question is why does return not accomplish anything here. Well, actually it does, you just don't see it because GHCi is hiding implementation details. GHCi has two fundamentally different modes of interactive evaluation:

  1. IO actions are executed, then the result printed.
  2. Everything else is printed as it is.

Crucially, GHCi tries rather hard to interpret everything as an IO action before proceeding with 2. So if you give it an ambiguous expression like return 0, it notices that one possible instantiation is IO Integer. It immediately defaults to that, executes this side-effect free action and all you see in the result is thus 0. This only happens for IO though, not for any other monads:

Prelude> return 0 :: IO Integer
0
Prelude> return 0 :: Maybe Integer
Just 0
Prelude> return 0 :: [] Integer
[0]

GHCi just happens to default to IO when the monad in ambiguous, but that wouldn't happen otherwise in Haskell as such.

like image 111
leftaroundabout Avatar answered Oct 21 '22 01:10

leftaroundabout