[Haskell-beginners] Ignoring the result of a monadic computation
Aleksandar Dimitrov
aleks.dimitrov at googlemail.com
Fri Nov 19 08:02:22 EST 2010
Hello Tim,
> while learning about monads, I had something like
>
> do
> line <- getLine
> something
> putStrLn line
This is written in do-notation. Let's look at it without do-notation:
> getLine >>= (\line -> something >>= (\_ -> putStrLn line))
Or, using `const` which is probably a bit clearer:
> getLine >>= (\line -> something >>= const $ putStrLn line)
The do-nation implicitly discards the result of 'something,' even though
something may have a result!
In fact, a couple of versions ago, ghc started warning you if 'something' had a
type other than M () and you weren't binding it:
> % cat Test.hs
> main :: IO ()
> main = do print "Hello"
> getChar
> print "Goodbye"
> % ghc -Wall --make Test.hs
> [1 of 1] Compiling Main ( Test.hs, Test.o )
>
> Test.hs:3:10:
> Warning: A do-notation statement discarded a result of type Char.
> Suppress this warning by saying "_ <- getChar",
> or by using the flag -fno-warn-unused-do-bind
So you'd have to rewrite your code like this to compile without warnings:
> do line <- getLine
> _ <- something
> putStrLn line
That way, it is clear that even though you're using the do-notation, you're
discarding the result of a computation, and are executing the computation just
for its side-effects!
> and I wondered if I could write it in one line, without naming of parameters.
As you can see above, one can write it in one line. It is also possible to use
(>>); (>>) is similar to (>>=) except it doesn't *bind* the result. It also has
a different type:
> (>>=) :: m a -> (a -> m b) -> m b
> (>>) :: m a -> m b -> m b
(>>=) expects a function from a to m b as a second argument, but since (>>)
doesn't bind a result at all, such a function wouldn't make any sense! So (>>)
just takes another computation, and chains these. You could rewrite the one-line
statement above as
> getLine >>= (\line -> something >> putStrLn line)
which does read a little better. But the do-notation really does make our lives
easier! It makes the λ-binding of variables more implicit. So we can use it in
the following way:
> do line <- getLine
> something >> putStrLn line
This way, it is clear that something's result is going to be thrown away (if
there is any,) and something is just executed for its side-effects.
> % cat Test.hs ~
> something = getChar
>
> main :: IO ()
> main = do line <- getLine
> something >> putStrLn line
> % ghc -Wall --make Test.hs
> % ./Test ~
> foobar
> .
> foobar
As you can see, I typed in 'foobar' which got bound to 'line.' But then I got
prompted to also put in a character, which got discarded.
I hope this makes it a little clearer!
A.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
Url : http://www.haskell.org/pipermail/beginners/attachments/20101119/b5d05217/attachment.bin
More information about the Beginners
mailing list