[英]Haskell: Running a list of IO operations over a single value
if I have a number of functions that are string -> IO ()
, is there a tidy way to apply them all to a single value in sequence. 如果我有许多函数是string -> IO ()
,是否有一种整洁的方式将它们全部应用于一个单独的值。
op1, op2, op3 :: String -> IO ()
main :: IO ()
main = do
let str = "test"
op1 str
op2 str
op3 str
with out having to write out str each time? 不必每次写出str?
Just use a map and partial application of function application ( $
): 只需使用功能应用程序( $
)的地图和部分应用程序:
mapM ($ str) [op1,op2,op3]
Don't want the result? 不想要结果? Fine. 精细。
mapM_ ($ str) [op1,op2,op3]
Or use Data.Foldable
: 或者使用Data.Foldable
:
for_ [op1,op2,op3] ($ str)
EDIT: 编辑:
Expanding on the commentary of for_
being a replacement for forM_
. 扩展了for_
替代forM_
。
The same can be said about mapM
/ mapM_
. 关于mapM
/ mapM_
。 These are artifacts of history - the operations are specialized to Monads and could, argueably should, be deleted. 这些是历史的工件 - 这些操作专门针对Monads,并且可以被删除。 The Applicative alternative is traverse
and traverse_
. 适用的替代方案是traverse
和traverse_
。
I'd recommend the for_
or traverse_
approach, but note that these Monoid
instances exist: 我建议使用for_
或traverse_
方法,但请注意这些Monoid
实例存在:
Monoid b => Monoid (a -> b)
Monoid a => Monoid (IO a)
Monoid ()
So in this particular case, this works: 所以在这种特殊情况下,这有效:
mconcat [op1, op2, op3] str
I would do 我会做
op1, op2, op3 :: String -> IO ()
main :: IO ()
main = do
let str = "test"
mconcat (sequence [op1, op2, op3] str)
This is somewhat complicated: sequence
here is specialized to type 这有点复杂:这里的sequence
专门用于输入
[String -> IO ()] -> String -> [IO ()]
while mconcat
simply takes a list of IO actions (type [IO ()]
) and returns a single IO action (type IO ()
). 而mconcat
只需要一个IO动作列表(类型[IO ()]
)并返回单个IO动作(类型IO ()
)。
Another solution, this one using ZipList
from Control.Applicative
: 另一个解决方案,这个使用来自Control.Applicative
ZipList
:
let ZipList ios = ZipList [op1,op2,op3] <*> ZipList (repeat str)
in sequence ios
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.