Haskell:在单个值上运行IO操作列表

时间:2018-04-12 04:50:00

标签: haskell

如果我有许多string -> IO ()的函数,是否有一种整齐的方式将它们全部应用于单个值。

op1, op2, op3 :: String -> IO ()

main :: IO ()
main = do
  let str = "test"
  op1 str
  op2 str
  op3 str

每次都要写出str吗?

4 个答案:

答案 0 :(得分:8)

只需使用功能应用程序的地图和部分应用程序($):

mapM ($ str) [op1,op2,op3]

不想要结果?细

mapM_ ($ str) [op1,op2,op3]

或使用Data.Foldable

for_ [op1,op2,op3] ($ str)

编辑:

扩展for_替代forM_的评论。

mapM / mapM_也是如此。这些是历史的工件 - 这些操作专门针对Monads,并且可以被删除。适用的替代方案是traversetraverse_

答案 1 :(得分:2)

我建议采用for_traverse_方法,但请注意这些Monoid个实例存在:

 Monoid b => Monoid (a -> b)
 Monoid a => Monoid (IO a)
 Monoid ()

所以在这种特殊情况下,这有效:

  mconcat [op1, op2, op3] str

答案 2 :(得分:1)

我愿意

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 ())。

答案 3 :(得分:0)

另一种解决方案,使用ZipList中的Control.Applicative

let ZipList ios = ZipList [op1,op2,op3] <*> ZipList (repeat str) 
 in sequence ios