
Hi, while learning about monads, I had something like do line <- getLine something putStrLn line and I wondered if I could write it in one line, without naming of parameters. I finally came up with getLine >>= ignore something >>= putStrLn using ignore :: Monad m => m a -> b -> m b ignore m a = m >> return a I'm satisfied with this solution but searching hoogle I didn't find a standard function for my ignore. Am I missing something? Cheers, Tim -- GRATIS! Movie-FLAT mit über 300 Videos. Jetzt freischalten unter http://portal.gmx.net/de/go/maxdome

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.

On Fri, Nov 19, 2010 at 07:56:02AM +0100, Tim Baumgartner wrote:
Hi,
while learning about monads, I had something like
do line <- getLine something putStrLn line
and I wondered if I could write it in one line, without naming of parameters. I finally came up with
getLine >>= ignore something >>= putStrLn
using ignore :: Monad m => m a -> b -> m b ignore m a = m >> return a
I'm satisfied with this solution but searching hoogle I didn't find a standard function for my ignore. Am I missing something?
Nope, there isn't such a function, but I like it. It reminds me of (*>) and (<*) from Control.Applicative. Note that you sometimes see the name 'ignore' used for a slightly different function, namely ignore :: Monad m => m a -> m () ignore m = m >> return () but yours is a bit more general. Other names for your function might be 'passThrough' or something like that. -Brent

On Fri, Nov 19, 2010 at 15:21, Brent Yorgey
On Fri, Nov 19, 2010 at 07:56:02AM +0100, Tim Baumgartner wrote:
Hi,
while learning about monads, I had something like
do line <- getLine something putStrLn line
and I wondered if I could write it in one line, without naming of parameters. I finally came up with
getLine >>= ignore something >>= putStrLn
using ignore :: Monad m => m a -> b -> m b ignore m a = m >> return a
I'm satisfied with this solution but searching hoogle I didn't find a standard function for my ignore. Am I missing something?
Nope, there isn't such a function, but I like it. It reminds me of (*>) and (<*) from Control.Applicative. Note that you sometimes see the name 'ignore' used for a slightly different function, namely
ignore :: Monad m => m a -> m () ignore m = m >> return ()
but yours is a bit more general. Other names for your function might be 'passThrough' or something like that.
I'm not sure I see any benefit of ': m a -> b -> m b' over 'm a -> m ()'. When would you want to use the former? /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus@therning.org Jabber: magnus@therning.org http://therning.org/magnus identi.ca|twitter: magthe

On Fri, Nov 19, 2010 at 03:26:04PM +0000, Magnus Therning wrote:
On Fri, Nov 19, 2010 at 15:21, Brent Yorgey
wrote: On Fri, Nov 19, 2010 at 07:56:02AM +0100, Tim Baumgartner wrote:
Hi,
while learning about monads, I had something like
do line <- getLine something putStrLn line
and I wondered if I could write it in one line, without naming of parameters. I finally came up with
getLine >>= ignore something >>= putStrLn
using ignore :: Monad m => m a -> b -> m b ignore m a = m >> return a
I'm satisfied with this solution but searching hoogle I didn't find a standard function for my ignore. Am I missing something?
Nope, there isn't such a function, but I like it. It reminds me of (*>) and (<*) from Control.Applicative. Note that you sometimes see the name 'ignore' used for a slightly different function, namely
ignore :: Monad m => m a -> m () ignore m = m >> return ()
but yours is a bit more general. Other names for your function might be 'passThrough' or something like that.
I'm not sure I see any benefit of ': m a -> b -> m b' over 'm a -> m ()'. When would you want to use the former?
From the OP's message:
getLine >>= ignore something >>= putStrLn which executes 'something' for its side effect and passes the result of getLine through to putStrLn, without ever having to give a name to the result of getLine. IIUC this was the whole point. -Brent

On Fri, Nov 19, 2010 at 15:31, Brent Yorgey
On Fri, Nov 19, 2010 at 03:26:04PM +0000, Magnus Therning wrote:
On Fri, Nov 19, 2010 at 15:21, Brent Yorgey
wrote: On Fri, Nov 19, 2010 at 07:56:02AM +0100, Tim Baumgartner wrote:
Hi,
while learning about monads, I had something like
do line <- getLine something putStrLn line
and I wondered if I could write it in one line, without naming of parameters. I finally came up with
getLine >>= ignore something >>= putStrLn
using ignore :: Monad m => m a -> b -> m b ignore m a = m >> return a
I'm satisfied with this solution but searching hoogle I didn't find a standard function for my ignore. Am I missing something?
Nope, there isn't such a function, but I like it. It reminds me of (*>) and (<*) from Control.Applicative. Note that you sometimes see the name 'ignore' used for a slightly different function, namely
ignore :: Monad m => m a -> m () ignore m = m >> return ()
but yours is a bit more general. Other names for your function might be 'passThrough' or something like that.
I'm not sure I see any benefit of ': m a -> b -> m b' over 'm a -> m ()'. When would you want to use the former?
From the OP's message:
getLine >>= ignore something >>= putStrLn
which executes 'something' for its side effect and passes the result of getLine through to putStrLn, without ever having to give a name to the result of getLine. IIUC this was the whole point.
IMNSHO, not such a strong argument for such a function though. :-) /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus@therning.org Jabber: magnus@therning.org http://therning.org/magnus identi.ca|twitter: magthe

On Fri, Nov 19, 2010 at 03:37:10PM +0000, Magnus Therning wrote:
On Fri, Nov 19, 2010 at 15:31, Brent Yorgey
wrote: On Fri, Nov 19, 2010 at 03:26:04PM +0000, Magnus Therning wrote:
On Fri, Nov 19, 2010 at 15:21, Brent Yorgey
wrote: On Fri, Nov 19, 2010 at 07:56:02AM +0100, Tim Baumgartner wrote:
Hi,
while learning about monads, I had something like
do line <- getLine something putStrLn line
and I wondered if I could write it in one line, without naming of parameters. I finally came up with
getLine >>= ignore something >>= putStrLn
using ignore :: Monad m => m a -> b -> m b ignore m a = m >> return a
I'm satisfied with this solution but searching hoogle I didn't find a standard function for my ignore. Am I missing something?
Nope, there isn't such a function, but I like it. It reminds me of (*>) and (<*) from Control.Applicative. Note that you sometimes see the name 'ignore' used for a slightly different function, namely
ignore :: Monad m => m a -> m () ignore m = m >> return ()
but yours is a bit more general. Other names for your function might be 'passThrough' or something like that.
I'm not sure I see any benefit of ': m a -> b -> m b' over 'm a -> m ()'. When would you want to use the former?
From the OP's message:
getLine >>= ignore something >>= putStrLn
which executes 'something' for its side effect and passes the result of getLine through to putStrLn, without ever having to give a name to the result of getLine. IIUC this was the whole point.
IMNSHO, not such a strong argument for such a function though. :-)
It depends what the "argument" is about. I agree there is not a strong argument for including such a function in the standard libraries. But it's a perfectly nice function to define and use in one's own code. Haskell makes this sort of abstraction very cheap. -Brent

On 19/11/10 19:20, Brent Yorgey wrote:
On Fri, Nov 19, 2010 at 03:37:10PM +0000, Magnus Therning wrote:
On Fri, Nov 19, 2010 at 15:31, Brent Yorgey
wrote: On Fri, Nov 19, 2010 at 03:26:04PM +0000, Magnus Therning wrote:
On Fri, Nov 19, 2010 at 15:21, Brent Yorgey
wrote: On Fri, Nov 19, 2010 at 07:56:02AM +0100, Tim Baumgartner wrote:
Hi,
while learning about monads, I had something like
do line <- getLine something putStrLn line
and I wondered if I could write it in one line, without naming of parameters. I finally came up with
getLine >>= ignore something >>= putStrLn
using ignore :: Monad m => m a -> b -> m b ignore m a = m >> return a
I'm satisfied with this solution but searching hoogle I didn't find a standard function for my ignore. Am I missing something?
Nope, there isn't such a function, but I like it. It reminds me of (*>) and (<*) from Control.Applicative. Note that you sometimes see the name 'ignore' used for a slightly different function, namely
ignore :: Monad m => m a -> m () ignore m = m >> return ()
but yours is a bit more general. Other names for your function might be 'passThrough' or something like that.
I'm not sure I see any benefit of ': m a -> b -> m b' over 'm a -> m ()'. When would you want to use the former?
From the OP's message:
getLine >>= ignore something >>= putStrLn
which executes 'something' for its side effect and passes the result of getLine through to putStrLn, without ever having to give a name to the result of getLine. IIUC this was the whole point.
IMNSHO, not such a strong argument for such a function though. :-)
It depends what the "argument" is about. I agree there is not a strong argument for including such a function in the standard libraries. But it's a perfectly nice function to define and use in one's own code. Haskell makes this sort of abstraction very cheap.
I can agree with that. /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus@therning.org Jabber: magnus@therning.org http://therning.org/magnus identi.ca|twitter: magthe

On 11/19/10 10:21, Brent Yorgey wrote:
On Fri, Nov 19, 2010 at 07:56:02AM +0100, Tim Baumgartner wrote:
using ignore :: Monad m => m a -> b -> m b ignore m a = m>> return a
I'm satisfied with this solution but searching hoogle I didn't find a standard function for my ignore. Am I missing something?
Nope, there isn't such a function, but I like it. It reminds me of (*>) and (<*) from Control.Applicative.
In fact, it is equal to: flip (<$) with <$ from Control.Applicative and it only needs a Functor constraint, not Monad or Applicative. http://haskell.org/ghc/docs/6.12.1/html/libraries/base/Control-Applicative.h... As y'all found out though, in this case an actual Applicative function looked like a cleaner way to write the parser. -Isaac

Hi Haskellers, this was my first post and I'm thankful and really impressed how many qualified answers I got. I've been learning Haskell only for a short time but I'm really fascinated how mathematical and expressive a programming language can be (I usually code Java). Recently I read a blog post, with a function map (length &&& head) . group that was much shorter and more elegant than the corresponding Python code. That was the main reason for me to try to write my own code in a single line without any lambda expressions. Regards Tim -------- Original-Nachricht --------
Datum: Fri, 19 Nov 2010 07:56:02 +0100 Von: "Tim Baumgartner"
An: beginners@haskell.org Betreff: [Haskell-beginners] Ignoring the result of a monadic computation
Hi,
while learning about monads, I had something like
do line <- getLine something putStrLn line
and I wondered if I could write it in one line, without naming of parameters. I finally came up with
getLine >>= ignore something >>= putStrLn
using ignore :: Monad m => m a -> b -> m b ignore m a = m >> return a
I'm satisfied with this solution but searching hoogle I didn't find a standard function for my ignore. Am I missing something?
Cheers, Tim -- GRATIS! Movie-FLAT mit über 300 Videos. Jetzt freischalten unter http://portal.gmx.net/de/go/maxdome _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- GRATIS! Movie-FLAT mit über 300 Videos. Jetzt freischalten unter http://portal.gmx.net/de/go/maxdome

On Fri, Nov 19, 2010 at 08:39:44PM +0100, Tim Baumgartner wrote:
Hi Haskellers,
this was my first post and I'm thankful and really impressed how many qualified answers I got. I've been learning Haskell only for a short time but I'm really fascinated how mathematical and expressive a programming language can be (I usually code Java). Recently I read a blog post, with a function
map (length &&& head) . group
that was much shorter and more elegant than the corresponding Python code. That was the main reason for me to try to write my own code in a single line without any lambda expressions.
Indeed! Writing code without lambda expressions or mentioning parameters is called "point-free style" (since parameters are sometimes referred to in the mathematical literature as "points"). For example, foo y = bar (baz (frob y)) can be rewritten as foo = bar . baz . frob which is (in most people's opinion) much nicer. Lambdabot (in the #haskell IRC channel on freenode.org) has a @pl command for performing such point-free simplifications. Point-free style should be taken in moderation, since it can be taken to unreadably esoteric extremes, but you are not in danger yet of crossing that line. =) -Brent

On Nov 19, 2010, at 7:56, Tim Baumgartner wrote:
Hi,
while learning about monads, I had something like
do line <- getLine something putStrLn line
and I wondered if I could write it in one line, without naming of parameters. I finally came up with
getLine >>= ignore something >>= putStrLn
using ignore :: Monad m => m a -> b -> m b ignore m a = m >> return a
I'm satisfied with this solution but searching hoogle I didn't find a standard function for my ignore. Am I missing something?
I don't know if this is better, but you could also write getLine >>= (something >>) . putStrLn Cheers, Bastian

"Tim Baumgartner"
while learning about monads, I had something like
do line <- getLine something putStrLn line
and I wondered if I could write it in one line, without naming of parameters. I finally came up with
getLine >>= ignore something >>= putStrLn
using ignore :: Monad m => m a -> b -> m b ignore m a = m >> return a
I'm satisfied with this solution but searching hoogle I didn't find a standard function for my ignore. Am I missing something?
Importing Control.Applicative, you can do this: getLine <* something >>= putStrLn The (<*) function has the following signature: (<*) :: (Applicative f) => f a -> f b -> f a It sequences the two computations in order, but returns the result of the first. This is mostly useful in applicative parsers, where you often need to skip unimportant stuff like spacing and use an earlier result. Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/

2010/11/20 Ertugrul Soeylemez
Importing Control.Applicative, you can do this:
getLine <* something >>= putStrLn
That's exactly what I was looking for. And indeed I wanted to consume some whitespace in a parser, just like you said. So I will start to read about Control.Applicative in Brent's Typeclassopedia soon. Thanks a lot Tim
participants (8)
-
Aleksandar Dimitrov
-
Bastian Erdnüß
-
Brent Yorgey
-
Ertugrul Soeylemez
-
Isaac Dupree
-
Magnus Therning
-
Tim Baumgartner
-
Tim Baumgartner