我正在使用Learn You a Haskell指南学习Haskell,而且我坚持在一系列函数列表中进行应用排序。 Chapter 11: Functors, Applicative Functors and Monoids将sequenceA定义为:
sequenceA :: (Applicative f) => [f a] -> f [a]
sequenceA [] = pure []
sequenceA (x:xs) = (:) <$> x <*> sequenceA xs
我对sequenceA的这个示例用法感到有点困惑:
> sequenceA [(+3),(+2),(+1)] 3
[6,5,4]
我已经尽可能地手动扩展应用程序,我认为是正确的:
(:) <$> (+3) <*> sequenceA [(+2), (+1)]
(:) <$> (+3) <*> (:) <$> (+2) <*> (:) <$> (+1) <*> sequenceA []
(:) <$> (+3) <*> (:) <$> (+2) <*> (:) <$> (+1) <*> pure []
(:) <$> (+3) <*> (:) <$> (+2) <*> (:) <$> (+1) <*> const []
我看不到的是,sequenceA的原始应用程序的第二个参数3
如何应用于列表中给出的每个部分应用的函数。我希望得到一些帮助,试图了解评估本声明的内容。
答案 0 :(得分:11)
每当您处理泛型类型时,您需要首先确定具体类型是什么。在这种情况下,我们有
sequenceA :: Applicative f => [f a] -> f [a]
适用于
[(+3),(+2),(+1)] :: Num a => [a -> a]
换句话说,虽然一开始看起来有点奇怪,但f
变为a ->
(正确编写(->) a
),因此sequenceA
的类型,专业,是
sequenceA :: Num a => [a -> a] -> a -> [a]
哪个应该已经解释了额外参数的来源。
那么sequenceA
如何运作?要理解,我们需要了解Applicative
的{{1}}实例。特别是
(->) a
我们看到instance Functor ((->) a) where
fmap f g = f . g
instance Applicative ((->) a) where
pure a' = \a -> a'
ff <*> fx = \a -> (ff a) (fx a)
接受两个函数并产生第三个函数。第三个函数的参数应用于每个输入函数(此处为(<*>)
和ff
),然后将它们的结果相互应用。
因此fx
monad中的应用意味着结果的最终参数(->) a
被分配给所有组合函数。
这就是我们在a
sequenceA
答案 1 :(得分:1)
使用:
instance Applicative ((->) a) where
pure = const
(<*>) f g x = f x (g x)
我们可以推导出:
(:) <$> (+3) <*> ( (:) <$> (+2) <*> ( (:) <$> (+1) <*> const [] ))
pure (:) <*> (+3) <*> ( pure (:) <*> (+2) <*> ( pure (:) <*> (+1) <*> const [] ))
const (:) <*> (+3) <*> (const (:) <*> (+2) <*> (const (:) <*> (+1) <*> const [] ))
(const (:) <*> (+3)) <*> ((const (:) <*> (+2)) <*> ((const (:) <*> (+1)) <*> const [] ))
(const (:) <*> (+3)) <*> ((const (:) <*> (+2)) <*> ((\x -> (const (:)) x (x+1)) <*> const [] ))
(const (:) <*> (+3)) <*> ((const (:) <*> (+2)) <*> ((\x -> (:) (x+1)) <*> const [] ))
(const (:) <*> (+3)) <*> ((const (:) <*> (+2)) <*> (\y -> (\x -> (:) (x+1)) y (const [] y) ))
(const (:) <*> (+3)) <*> ((const (:) <*> (+2)) <*> (\y -> (\x -> (:) (x+1)) y [] ))
(const (:) <*> (+3)) <*> ((const (:) <*> (+2)) <*> (\y -> ((y+1):) [] ))
(const (:) <*> (+3)) <*> ((const (:) <*> (+2)) <*> (\y -> [y+1] ))
(const (:) <*> (+3)) <*> (((\x -> (const (:)) x (x+2)) <*> (\y -> [y+1] ))
(const (:) <*> (+3)) <*> (\z -> ((\x -> (const (:)) x (x+2)) z ((\y -> [y+1] )z))
(const (:) <*> (+3)) <*> (\z -> (((const (:)) z (z+2)) ([z+1]))
(const (:) <*> (+3)) <*> (\z -> ((z+2):) [z+1])
(const (:) <*> (+3)) <*> (\z -> [z+2,z+1])
(\x -> (const (:)) x (x+3)) <*> (\z -> [z+2,z+1])
(\x -> const (:) (x+3)) <*> (\z -> [z+2,z+1])
(\x -> ((x+3):)) <*> (\z -> [z+2,z+1])
\w -> (\x -> ((x+3):)) w ((\z -> [z+2,z+1]) w)
\w -> ((w+3):) [w+2,w+1]
\w -> [w+3,w+2,w+1]
我打赌我搞砸了一些括号