在同一个输入上调用多个 IO 函数
Call multiple IO functions on the same input
假设我有一个元组列表(例如 [(a,b)]
),每个元组都是先前计算的结果。
而且我想在这些元素中的每一个上应用几个函数(例如,一个函数可能打印它,另一个函数通过网络发送它等)
我尝试过的:
import Control.Applicative
main = do
let a = [1..5]
let fs = [(\k-> putStrLn $ show $ k*2), (\k-> putStrLn $ show $ k-2), (\k-> putStrLn $ show $ k*10)]
let res = fs <*> a
putStrLn $ "Yo"
仅打印 "Yo"
.
如果你仔细观察 res
有类型 [IO ()]
而你从不使用它。
所以只是sequence
它:
main = do
let a = [1..5]
let fs = [(\k-> putStrLn $ show $ k*2), (\k-> putStrLn $ show $ k-2), (\k-> putStrLn $ show $ k*10)]
let res = fs <*> a
sequence res
putStrLn $ "Yo"
如果您想知道如何使整个块更简洁,而不是重构映射列表(使用 部分 ),请选择 print
(这基本上是你的 putStrLn . show
)和 mapM_
:
main = do
mapM_ print $ [(* 2), (+ (-2)), (* 10)] <*> [1..5]
putStrLn $ "Yo"
这会给
λ> :main
2
4
6
8
10
-1
0
1
2
3
10
20
30
40
50
Yo
还有 ;)
请注意,您可能不应该将所有 IO
内容与更纯粹的计算混合在一起 - 相反,我会重构整数列表:
myCombinations :: [Int] -> [Int]
myCombinations ns = [(* 2), (+ (-2)), (* 10)] <*> ns
main = do
mapM_ print $ myCombinations [1..5]
putStrLn $ "Yo"
(当然会边走边介绍功能,但我猜不出你想在这里实现什么)
由此您可以只检查您的纯 functions/values:
λ> myCombinations [1..5]
[2,4,6,8,10,-1,0,1,2,3,10,20,30,40,50]
并可能获得很多可读性;)
如果您有 ios :: [a -> IO b]
的列表,您可以使用 mapM ($ aValue) ios
获取 IO [b]
或使用 mapM_
获取 IO ()
let
不会将任何东西绑定到 monad 中。所以 IO
不关心你用 <*>
做什么来应用列表中的函数,只要你不以任何方式在 monad 操作中使用结果。
要简单地执行一系列操作......好吧,序列,您可以使用sequence
:
let res = fs <*> a
sequence res
假设我有一个元组列表(例如 [(a,b)]
),每个元组都是先前计算的结果。
而且我想在这些元素中的每一个上应用几个函数(例如,一个函数可能打印它,另一个函数通过网络发送它等)
我尝试过的:
import Control.Applicative
main = do
let a = [1..5]
let fs = [(\k-> putStrLn $ show $ k*2), (\k-> putStrLn $ show $ k-2), (\k-> putStrLn $ show $ k*10)]
let res = fs <*> a
putStrLn $ "Yo"
仅打印 "Yo"
.
如果你仔细观察 res
有类型 [IO ()]
而你从不使用它。
所以只是sequence
它:
main = do
let a = [1..5]
let fs = [(\k-> putStrLn $ show $ k*2), (\k-> putStrLn $ show $ k-2), (\k-> putStrLn $ show $ k*10)]
let res = fs <*> a
sequence res
putStrLn $ "Yo"
如果您想知道如何使整个块更简洁,而不是重构映射列表(使用 部分 ),请选择 print
(这基本上是你的 putStrLn . show
)和 mapM_
:
main = do
mapM_ print $ [(* 2), (+ (-2)), (* 10)] <*> [1..5]
putStrLn $ "Yo"
这会给
λ> :main
2
4
6
8
10
-1
0
1
2
3
10
20
30
40
50
Yo
还有 ;)
请注意,您可能不应该将所有 IO
内容与更纯粹的计算混合在一起 - 相反,我会重构整数列表:
myCombinations :: [Int] -> [Int]
myCombinations ns = [(* 2), (+ (-2)), (* 10)] <*> ns
main = do
mapM_ print $ myCombinations [1..5]
putStrLn $ "Yo"
(当然会边走边介绍功能,但我猜不出你想在这里实现什么)
由此您可以只检查您的纯 functions/values:
λ> myCombinations [1..5]
[2,4,6,8,10,-1,0,1,2,3,10,20,30,40,50]
并可能获得很多可读性;)
如果您有 ios :: [a -> IO b]
的列表,您可以使用 mapM ($ aValue) ios
获取 IO [b]
或使用 mapM_
获取 IO ()
let
不会将任何东西绑定到 monad 中。所以 IO
不关心你用 <*>
做什么来应用列表中的函数,只要你不以任何方式在 monad 操作中使用结果。
要简单地执行一系列操作......好吧,序列,您可以使用sequence
:
let res = fs <*> a
sequence res