我有
functions :: IO[a -> b] -- IO List of functions
param :: IO[a] -- Single parameter
我希望得到
result :: IO[b]
result = IO[*first function* <$> param, *second function* <$> param, ...]
我不知何故可以得到IO[IO b]
类型的结果,但我想要IO[b]
答案 0 :(得分:7)
通过“单个参数”我假设你的意思是一个元素列表。如果是这样,那么这就是它的完成方式:
result :: IO [b]
result = do
fs <- functions -- fs :: [a -> b]
xs <- param -- xs :: [a]
let ys = fs <*> xs -- ys :: [b]
return ys
请注意,由于xs
是一个元素列表,因此您基本上将fs
的每个元素应用于该值。
这与:
相同import Control.Applicative (liftA2)
result :: IO [b]
result = liftA2 (<*>) functions param
希望有所帮助。
答案 1 :(得分:4)
这看起来非常像一个简单的<*>
,但我们需要深入调用它。我们是否可以仅使用Applicative
实例执行此操作,而无需使用Monad
?
首先解决一个更简单的问题:
functions :: IO (a -> b)
param :: IO a
我们可以使用:
functions <*> param
获得IO b
。
同样,给定一个函数列表和一个值列表:
functions :: [a -> b]
param :: [a]
我们可以使用:
functions <*> param
获得[b]
。
但现在要同时做两件事:
functions :: IO [a -> b]
param :: IO [a]
这是......比较棘手,因为我们必须同时利用Applicative
的{{1}}个实例和IO
的{{1}}个实例。但它仍然可行:
Applicative
或者更简洁但更难(对我来说)解析:
[]
或者,根据blunt:
doubleAp fns x = liftedFns <*> x
where apList = (<*>) :: [a -> b] -> [a] -> [b]
liftedFns = fmap apList fns :: IO ([a] -> [b])
答案 2 :(得分:3)
sequence
会让您从[IO b]
转到IO [b]
,join
会让您从IO (IO [b])
转到IO [b]
。