【问题标题】:Mapping over IO in Haskell在 Haskell 中映射 IO
【发布时间】:2010-07-01 15:49:22
【问题描述】:

是否有传统的方法来映射使用 IO 的函数?具体来说,我想映射一个返回某种随机值的函数。使用法线贴图会产生类型为 ([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] []

【问题讨论】:

  • 以后试试 [Hoogle](haskell.org/hoogle/… 看看是否已经存在一些看似显而易见的功能(因为它们通常都有)。它非常有用!
  • 谢谢,这看起来是一个很棒的资源!
  • 另外,看看 Hayoo - 它就像 Hoogle,但检查的东西略有不同。

标签: haskell random io


【解决方案1】:

标准方式是通过:

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

按顺序实现:

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

【讨论】:

  • 谢谢!正是我想要的。
【解决方案2】:

为了补充 Don 的答案,还请看一下 mapM_ 函数,它与 mapM 完全一样,但会丢弃所有结果,因此您只会得到副作用。

如果您希望执行计算(例如 IO 计算)但对结果不感兴趣(例如取消链接文件),这很有用。

另请参阅forMforM_

【讨论】:

  • 并且 mapM_ 在恒定堆栈空间中运行,而 mapM 需要线性堆栈,对于 sequence_ 与 sequence 类似。
  • @Simon,感谢您提及这一点。我总是非常仔细地查看我的 mapM,以确保列表很小或尝试重构以使用 mapM_。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-22
  • 1970-01-01
  • 2012-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多