假设我有一个元组列表(例如[(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"
。
答案 0 :(得分:4)
如果仔细观察,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"
如果您想知道如何使整个块更简洁,而不是重构映射列表(使用 sections ),请使用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"
(当然,随着你的进展引入功能,但我无法猜测你在这里想要实现的目标)
从中你可以检查你的纯函数/值:
λ> myCombinations [1..5]
[2,4,6,8,10,-1,0,1,2,3,10,20,30,40,50]
并且可能获得很多可读性;)
答案 1 :(得分:0)
如果您有ios :: [a -> IO b]
列表,则可以使用mapM ($ aValue) ios
获取IO [b]
或mapM_
获取IO ()
答案 2 :(得分:0)
let
不会将任何内容绑定到monad中。因此IO
并不关心您使用<*>
对列表中的函数进行操作,只要您不以任何方式在monad操作中使用结果。
要简单地执行......井,序列中的操作列表,您可以使用sequence
:
let res = fs <*> a
sequence res