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

bpa*_*rni 6 haskell

我正在学习Haskell和Learn You a Haskell指南,并且我在一系列函数中坚持使用应用程序排序的例子.第11章:Functors,Applicative Functors和Monoids将sequenceA定义为:

sequenceA :: (Applicative f) => [f a] -> f [a]
sequenceA [] = pure []
sequenceA (x:xs) = (:) <$> x <*> sequenceA xs
Run Code Online (Sandbox Code Playgroud)

我对sequenceA的这个示例用法感到有点困惑:

> sequenceA [(+3),(+2),(+1)] 3
[6,5,4]
Run Code Online (Sandbox Code Playgroud)

我已尽可能手动扩展应用程序,我认为是正确的:

(:) <$> (+3) <*> sequenceA [(+2), (+1)]
(:) <$> (+3) <*> (:) <$> (+2) <*> (:) <$> (+1) <*> sequenceA []
(:) <$> (+3) <*> (:) <$> (+2) <*> (:) <$> (+1) <*> pure []
(:) <$> (+3) <*> (:) <$> (+2) <*> (:) <$> (+1) <*> const []
Run Code Online (Sandbox Code Playgroud)

我没有看到的是,sequenceA的原始应用程序的第二个参数如何3应用于列表中给出的每个部分应用的函数.我希望得到一些帮助,试图了解评估本声明的内容.

J. *_*son 12

无论何时处理泛型类型,都需要首先确定具体类型.在这种情况下,我们有

sequenceA :: Applicative f => [f a] -> f [a]
Run Code Online (Sandbox Code Playgroud)

应用于

[(+3),(+2),(+1)] :: Num a => [a -> a]
Run Code Online (Sandbox Code Playgroud)

换句话说,虽然起初看起来有点奇怪,但是f变得a ->(正确写入(->) a)所以sequenceA专业的类型是

sequenceA :: Num a => [a -> a] -> a -> [a]
Run Code Online (Sandbox Code Playgroud)

哪个应该已经解释了额外论点的来源.


那怎么sequenceA工作?要理解,我们需要了解Applicative实例(->) 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)
Run Code Online (Sandbox Code Playgroud)

我们看到它(<*>)需要两个函数并生成第三个函数.来自第三个函数的参数应用于每个输入函数(此处fffx),然后将它们的结果相互应用.

因此,在(->) amonad中的应用意味着结果的最终参数a被分配给所有组合函数.

这就是我们所看到的 sequenceA

sequenceA [(+3),(+2),(+1)]
==
\a -> [(a + 3), (a + 2), (a + 1)]
Run Code Online (Sandbox Code Playgroud)