general structuring of "foreach" logic in IO

This works: main = do myargs <- getArgs mapM_ (\s -> putStrLn s ) myargs and imagine that the "body" will be substantial rather than just a putStrLn. My gut instinct is that the code ought to be arranged as: <any needed keywords or punctuation> and <the collection of items>
Meanwhile, there is no need to name the result of getArgs into myargs. So, getArgs is of type IO [String], and I want to apply that in the manner of a list. Without the Monad wrappers, plain map ( blah ) strings could be ( blah ) <$> strings, and in this particular case I don't see a reversed-arg version, although there is one for <*> (as <**>). But, for monad stuff in general there are reversed arrows for (most?) everything, and that's where I'm heading. So the first question is, how do I do the equivalent map-as-nondeterministic-apply when the strings is further wrapped in IO, as is the function being applied. getArgs >>= mapM_ (\s -> putStrLn s ) does double-duty of moving the argument from last place to the left, as it makes use of eta reduction. Because I have two things going on (list applicative and IO monad) I'm losing the slickness of using applicative syntax. Is there a nice way to make these work together? And more generally, how would you write such a construct? I'm naturally biased with my knowledge in other languages, so maybe there's a completely different "normal" way of approaching this? Thanks, -John
On Sat, Apr 12, 2014 at 08:29:09AM -0500, John M. Dlugosz wrote:
This works:
main = do myargs <- getArgs mapM_ (\s -> putStrLn s ) myargs
and imagine that the "body" will be substantial rather than just a putStrLn. My gut instinct is that the code ought to be arranged as:
<any needed keywords or punctuation> and <the collection of items>
Meanwhile, there is no need to name the result of getArgs into myargs.
So, getArgs is of type IO [String], and I want to apply that in the manner of a list. Without the Monad wrappers, plain map ( blah ) strings could be ( blah ) <$> strings, and in this particular case I don't see a reversed-arg version, although there is one for <*> (as <**>). But, for monad stuff in general there are reversed arrows for (most?) everything, and that's where I'm heading.
So the first question is, how do I do the equivalent map-as-nondeterministic-apply when the strings is further wrapped in IO, as is the function being applied.
getArgs >>= mapM_ (\s -> putStrLn s )
does double-duty of moving the argument from last place to the left, as it makes use of eta reduction. Because I have two things going on (list applicative and IO monad) I'm losing the slickness of using applicative syntax. Is there a nice way to make these work together?
And more generally, how would you write such a construct? I'm naturally biased with my knowledge in other languages, so maybe there's a completely different "normal" way of approaching this?
I'm not entirely sure I get what you are asking for, but I'll take a stab and just let me know if I'm completely off the mark. If all you want is keep the 'string generator' on the right-hand side, then you have (=<<): mapM_ putStrLn =<< getArgs Personally I often like keeping the 'string generator' on the left (i.e. using (>>=) because when the expression to be mapped grows it allows this structuring of the code: getArgs >>= mapM_ $ \ s -> do ... /M -- Magnus Therning OpenPGP: 0xAB4DFBA4 email: magnus@therning.org jabber: magnus@therning.org twitter: magthe http://therning.org/magnus Perl is another example of filling a tiny, short-term need, and then being a real problem in the longer term. -- Alan Kay

@John
It looks like you are looking for `forM_` from Control.Monad:
http://hackage.haskell.org/package/base-4.7.0.0/docs/Control-Monad.html#v:fo...
That way you can write code that looks like:
main = do
myargs <- getArgs
forM_ myargs $ \s -> do
putStrLn s
putStrLn $ "Second string" ++ s
This is just `mapM_` with the its two parameters fliped. `forM_` is defined
in a an idiomatic fashion, with the `flip`(prelude function) function.
Definition of forM_
http://hackage.haskell.org/package/base-4.7.0.0/docs/src/Control-Monad.html#...
Magnus solution has been used so often by some people that some have
created idioms around it.
om f m x = m >>= flip f x
main = do
om forM_ getArgs $ \s -> do
putStrLn s
putStrLn $ "Second string: " ++ s
You can read the discussion around om:
http://www.reddit.com/r/haskell/comments/1i2zmq/a_useful_function_om/
Hope that helps.
Patrick
On Sun, Apr 13, 2014 at 1:48 AM, Magnus Therning
This works:
main = do myargs <- getArgs mapM_ (\s -> putStrLn s ) myargs
and imagine that the "body" will be substantial rather than just a
On Sat, Apr 12, 2014 at 08:29:09AM -0500, John M. Dlugosz wrote: putStrLn.
My gut instinct is that the code ought to be arranged as:
<any needed keywords or punctuation> and <the collection of items>
Meanwhile, there is no need to name the result of getArgs into myargs.
So, getArgs is of type IO [String], and I want to apply that in the manner of a list. Without the Monad wrappers, plain map ( blah ) strings could be ( blah ) <$> strings, and in this particular case I don't see a reversed-arg version, although there is one for <*> (as <**>). But, for monad stuff in general there are reversed arrows for (most?) everything, and that's where I'm heading.
So the first question is, how do I do the equivalent map-as-nondeterministic-apply when the strings is further wrapped in IO, as is the function being applied.
getArgs >>= mapM_ (\s -> putStrLn s )
does double-duty of moving the argument from last place to the left, as it makes use of eta reduction. Because I have two things going on (list applicative and IO monad) I'm losing the slickness of using applicative syntax. Is there a nice way to make these work together?
And more generally, how would you write such a construct? I'm naturally biased with my knowledge in other languages, so maybe there's a completely different "normal" way of approaching this?
I'm not entirely sure I get what you are asking for, but I'll take a stab and just let me know if I'm completely off the mark.
If all you want is keep the 'string generator' on the right-hand side, then you have (=<<):
mapM_ putStrLn =<< getArgs
Personally I often like keeping the 'string generator' on the left (i.e. using (>>=) because when the expression to be mapped grows it allows this structuring of the code:
getArgs >>= mapM_ $ \ s -> do ...
/M
-- Magnus Therning OpenPGP: 0xAB4DFBA4 email: magnus@therning.org jabber: magnus@therning.org twitter: magthe http://therning.org/magnus
Perl is another example of filling a tiny, short-term need, and then being a real problem in the longer term. -- Alan Kay
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Patrick Wheeler Patrick.John.Wheeler@gmail.com Patrick.J.Wheeler@rice.edu Patrick.Wheeler@colorado.edu

On 4/14/2014 4:34 AM, Patrick Wheeler wrote:
@John That way you can write code that looks like:
main = do myargs <- getArgs forM_ myargs $ \s -> do putStrLn s putStrLn $ "Second string" ++ s
That still introduces a throw-away name and extracts the args on another line. Is there a way to do something like: main = do forM_ (dereference getArgs) $ \s -> do ... or mforM_ getArgs $ \s -> do ...
You can read the discussion around om: http://www.reddit.com/r/haskell/comments/1i2zmq/a_useful_function_om/
Thanks, I will. I guess it bothers me that "wrapped" values in the IO monad can't be independently used in situ, but need to be given a name on another line first. Isn't the likes of "lift" and (even nicer) <*> supposed to address this idea? I can't quite see why that doesn't work here. (And that begs the question of why getArgs needs to be monadic in the first place. It doesn't change its value; it's a strict constant at run-time, and not knowing it at compile time is my problem how?) —John

On Mon, Apr 14, 2014 at 11:41 AM, John M. Dlugosz
(And that begs the question of why getArgs needs to be monadic in the first place. It doesn't change its value; it's a strict constant at run-time, and not knowing it at compile time is my problem how?)
But it is the *compiler's* problem. "Constant" means "known at compile time" to the compiler. Although I wonder if you'd be happier with getArgs >>= mapM_ (do ...). -- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

On 4/14/2014 10:47 AM, Brandon Allbery wrote:
But it is the *compiler's* problem. "Constant" means "known at compile time" to the compiler.
Pure means pure at run-time over the life of the executable. Just because the compiler doesn't know what it is (had it cared to evaluate it at compile time) doesn't mean it's not pure.
Although I wonder if you'd be happier with getArgs >>= mapM_ (do ...).
That's what I ended up with when I stopped fiddling with that particular line.

On Mon, Apr 14, 2014 at 2:37 PM, John M. Dlugosz
On 4/14/2014 10:47 AM, Brandon Allbery wrote:
But it is the *compiler's* problem. "Constant" means "known at compile time" to the compiler.
Pure means pure at run-time over the life of the executable. Just because the compiler doesn't
To you. To the compiler, and to me actually, if it is not known at compile time then it cannot be pure; it may not vary over an individual run of the program but it can vary over the lifetime of the program itself. If I cannot know it *statically* --- at compile time, since it is the compiler that needs to know that it is static --- then it is not pure. -- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

getArgs is not pure in the presence of withArgs.
This is actually what we want; testing/exercising code that uses
getArgs would be a pain otherwise.
On Mon, Apr 14, 2014 at 11:42 AM, Brandon Allbery
On Mon, Apr 14, 2014 at 2:37 PM, John M. Dlugosz
wrote: On 4/14/2014 10:47 AM, Brandon Allbery wrote:
But it is the *compiler's* problem. "Constant" means "known at compile time" to the compiler.
Pure means pure at run-time over the life of the executable. Just because the compiler doesn't
To you. To the compiler, and to me actually, if it is not known at compile time then it cannot be pure; it may not vary over an individual run of the program but it can vary over the lifetime of the program itself. If I cannot know it *statically* --- at compile time, since it is the compiler that needs to know that it is static --- then it is not pure.
-- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (5)
-
Brandon Allbery
-
David Thomas
-
John M. Dlugosz
-
Magnus Therning
-
Patrick Wheeler