Отображение IO в Haskell - PullRequest
8 голосов
/ 01 июля 2010

Существует ли традиционный способ сопоставления функции, использующей ввод-вывод? В частности, я хотел бы отобразить на функцию, которая возвращает случайное значение некоторого вида. Использование карты нормалей приведет к выводу типа ([IO b]), но для распаковки значений в списке из IO мне нужно что-то типа (IO [b]). Итак, я написал ...

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)

... который отлично работает. Но, похоже, для этого должно быть решение, встроенное в Haskell. Например, пример использования:

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

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

Ответы [ 2 ]

23 голосов
/ 01 июля 2010

Стандартный способ:

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

, который реализуется в терминах последовательности:

sequence :: (Monad m) => [m a] -> m [a]
12 голосов
/ 01 июля 2010

Просто чтобы добавить ответ Дона, взгляните также на функцию mapM_, которая делает именно то, что делает mapM, но отбрасывает все результаты, поэтому вы получаете только побочные эффекты.

Это полезно, если вы хотите, чтобы выполнялись вычисления (например, вычисления ввода-вывода), но вы не заинтересованы в результате (например, отмена связывания файлов).

А также см. forM и forM_.

...