[英]Haskell: Running a list of IO operations over a single value
如果我有许多函数是string -> IO ()
,是否有一种整洁的方式将它们全部应用于一个单独的值。
op1, op2, op3 :: String -> IO ()
main :: IO ()
main = do
let str = "test"
op1 str
op2 str
op3 str
不必每次写出str?
只需使用功能应用程序( $
)的地图和部分应用程序:
mapM ($ str) [op1,op2,op3]
不想要结果? 精细。
mapM_ ($ str) [op1,op2,op3]
或者使用Data.Foldable
:
for_ [op1,op2,op3] ($ str)
编辑:
扩展了for_
替代forM_
。
关于mapM
/ mapM_
。 这些是历史的工件 - 这些操作专门针对Monads,并且可以被删除。 适用的替代方案是traverse
和traverse_
。
我建议使用for_
或traverse_
方法,但请注意这些Monoid
实例存在:
Monoid b => Monoid (a -> b)
Monoid a => Monoid (IO a)
Monoid ()
所以在这种特殊情况下,这有效:
mconcat [op1, op2, op3] str
我会做
op1, op2, op3 :: String -> IO ()
main :: IO ()
main = do
let str = "test"
mconcat (sequence [op1, op2, op3] str)
这有点复杂:这里的sequence
专门用于输入
[String -> IO ()] -> String -> [IO ()]
而mconcat
只需要一个IO动作列表(类型[IO ()]
)并返回单个IO动作(类型IO ()
)。
另一个解决方案,这个使用来自Control.Applicative
ZipList
:
let ZipList ios = ZipList [op1,op2,op3] <*> ZipList (repeat str)
in sequence ios
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.