在这种情况下,您需要:
liftA2 (*) <$> Just [1, 2, 3] <*> Just [4, 5, 6, 7]
或者:
liftA2 (liftA2 (*)) (Just [1, 2, 3]) (Just [4, 5, 6, 7])
外层… <$> … <*> … 或liftA2 作用于Maybe,而内层作用于[]。如果您不知道这一点,您可以通过向 GHCi 询问您应该放在那里的内容类型来弄清楚,例如使用类型孔:
:t _ <$> (Just [1 :: Int, 2, 3]) <*> (Just [4 :: Int, 5, 6, 7]) :: Maybe [Int]
它回馈:
_ :: [Int] -> [Int] -> [Int]
您想要组合列表的行为是\ xs ys -> (*) <$> xs <*> ys,可以缩写为liftA2 (*)。 ((*) <$>) 或 fmap (*) 不起作用,因为这只是您需要的一半:它在单个列表上运行(使用 Functor),而您想组合两个列表(使用 Applicative)。
当然,liftA2 (liftA2 (*)) 适用于任何两个元素为数字的嵌套应用函子:
(Applicative f, Applicative g, Num a)
=> f (g a) -> f (g a) -> f (g a)
例如嵌套列表:
liftA2 (liftA2 (*)) [[1], [2], [3]] [[4, 5, 6]]
== [[4,5,6],[8,10,12],[12,15,18]]
-- (Transposing the inputs transposes the output.)
liftA2 (liftA2 (*)) [[1, 2, 3]] [[4], [5], [6]]
== [[4,8,12],[5,10,15],[6,12,18]]
或Maybe的列表:
liftA2 (liftA2 (*)) [Just 1, Nothing, Just 3] [Just 4, Nothing, Just 6]
== [Just 4, Nothing, Just 6,
Nothing, Nothing, Nothing,
Just 12, Nothing, Just 18]
甚至更奇特的东西,比如函数列表:
($ (3, 5)) <$> (liftA2 (+) <$> [fst, snd] <*> [snd, fst])
== [fst (3, 5) + snd (3, 5),
fst (3, 5) + fst (3, 5),
snd (3, 5) + snd (3, 5),
snd (3, 5) + fst (3, 5)]
== [3+5, 3+3, 5+5, 5+3]
== [8,6,10,8]