Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looping over Monads in Haskell

Tags:

haskell

I am really new to Haskell, so this might be a stupid question. I have a function

foo :: Int -> IO ()

whose result will print some useful information. Now I want to do this:

do
    foo 0
    foo 1
    foo 0
    foo 2
    foo 3

How can I write this as a loop? My problem is to 'concatenate' the Monads, which is done automatically by the do statement...

Thank you for your help!

like image 969
Sh4pe Avatar asked Feb 10 '13 13:02

Sh4pe


People also ask

What is a monad in Haskell?

Haskell - Monads. Monads are nothing but a type of Applicative Functor with some extra features. It is a Type class which governs three basic rules known as monadic rules. Left Identity Law − The return function does not change the value and it should not change anything in the Monad.

What is the best way to loop in Haskell?

When the builtin traversals don’t obviously provide something you actually want, the end-all solution is the tail-recursive loop. This is the most manual way to loop in Haskell, and as such it’s the most flexible.

How can I sequence my chopsticks in Haskell?

In Haskell, the sequencing can be done using the standard monadic functions: assemblyLine::Wood->TrayWrappedChopsticksassemblyLinew=(returnw)>>=makeChopsticks>>=polishChopsticks>>=wrapChopsticks or using the built in Haskell "do" notation for monads:

What are I/O actions in Haskell?

However, values in the IO monad are often called I/O actions and we will use that terminology here. In Haskell, the top-level mainfunction must have type IO (), so that programs are typically structured at the top level as an imperative-style sequence of I/O actions and calls to functional-style code.


2 Answers

mapM_ foo [0,1,0,2,3] will do the trick.

What's perhaps more important is "how does one figure that out?" Hoogle is a wonderful tool. You want to apply a function with signature Int -> IO () to a bunch of Ints to get a new IO action. The thing you're looking for will thus have signature (Int -> IO ()) -> [Int] -> IO (), so we go and ask Hoogle for functions with that signature. The second result is mapM_, whose signature is

Monad m => (a -> m b) -> [a] -> m ()

Right, so mapM_ in fact works with any monad (not just IO) and any type (not just Int). When you think about it, that's not surprising at all.

like image 97
gspr Avatar answered Sep 20 '22 00:09

gspr


You want the mapM_ combinator, which maps a function returning a monadic value over a list, and uses the bind operator to sequence the results:

>> let foo n = putStrLn (show n ++ "!")
>> mapM_ foo [0,1,0,2,3]
0!
1!
0!
2!
3!

Sometimes people like to use the flipped version

for :: Monad m => [a] -> (a -> m b) -> m ()
for = flip mapM_

which looks more like imperative code:

>> for [1..5] $ \n ->
     putStrLn ("Number: " ++ show n)
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5

Note that a combinator called forM_ is defined in Control.Monad and does exactly the same thing as the combinator I've called for.

like image 36
Chris Taylor Avatar answered Sep 20 '22 00:09

Chris Taylor