简体   繁体   中英

Mapping over IO in Haskell

Is there a traditional way to map over a function that uses IO? Specifically, I'd like to map over a function that returns a random value of some kind. Using a normal map will result in an output of type ([IO b]), but to unpack the values in the list from IO, I need a something of type (IO [b]). So I wrote...

mapIO :: (a -> IO b) -> [a] -> [b] -> IO [b]
mapIO f [] acc = do return acc
mapIO f (x:xs) acc = do
  new <- f x
  mapIO f xs (new:acc)

... which works fine. But it seems like there ought to be a solution for this built into Haskell. For instance, an example use case:

getPercent :: Int -> IO Bool
getPercent x = do
  y <- getStdRandom (randomR (1,100))
  return $ y < x

mapIO (\f -> getPercent 50) [0..10] []

The standard way is via:

Control.Monad.mapM :: (Monad m) => (a -> m b) -> [a] -> m [b]

which is implemented in terms of sequence:

sequence :: (Monad m) => [m a] -> m [a]

Just to add to Don's answer, hake a look to the mapM_ function as well, which does exactly what mapM does but discards all the results so you get only side-effects.

This is useful if you want the have computations executed (for example IO computations) but are not interested in the result (for example, unlinking files).

And also see forM and forM_ .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM