应用IO [a - > b]到a类型的单个参数

时间:2016-01-08 19:47:25

标签: function haskell functional-programming

我有

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]

3 个答案:

答案 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]