函数sendrecv具有以下类型签名:
sendrecv :: Socket ->
PSQ.PSQ (String, Integer) POSIXTime ->
Map.Map (String, Integer) [String] ->
String ->
IO (PSQ.PSQ (String, Integer) POSIXTime, Map.Map (String, Integer) [String])
它需要一个套接字,一个PSQ,一个Map和一个String,并返回一个PSQ和一个Map。
我想把它调用n次,其中套接字和字符串保持不变,但PSQ和Map得到修改,意味着修改后的PSQ,Map应该成为下一次运行的输入。
最初我认为这对于foldM来说可能是一个完美的例子,并尝试过例如
(q', m') <- foldM sendrecv (s, q1, m1, "ping") (enumFromTo 1 1000)
但显然这不起作用,我担心我还没有理解整个foldM的事情,或者是否有可能传递静态参数(如s和“ping”)以及如何。
答案 0 :(得分:5)
如果您定义辅助函数
iterateM :: Monad m => Int -> (a -> m a) -> a -> m a
iterateM 0 _ x = return x
iterateM n f x = iterateM (n - 1) f =<< f x
sendRecv' socket string (q, m) = sendRecv socket q m string
然后你可以写
(q', m') <- iterateM 1000 (sendRecv' s "ping") (q1, m1)
(我对iterateM
之类的东西不标准感到有些惊讶。)
话虽如此,以下是使用foldM
:
(q', m') <- foldM (flip . const $ sendRecv' s "ping") (q1, m1) [1..1000]
或
(q', m') <- foldM (\(q, m) _ -> sendRecv s q m "ping") (q1, m1) [1..1000]
但我不认为在这里使用foldM
会产生清晰的代码。