对功能列表的应用排序如何工作?

时间:2014-06-30 22:41:27

标签: haskell

我正在使用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如何应用于列表中给出的每个部分应用的函数。我希望得到一些帮助,试图了解评估本声明的内容。

2 个答案:

答案 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]
我打赌我搞砸了一些括号