我正在学习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)
我们看到它(<*>)需要两个函数并生成第三个函数.来自第三个函数的参数应用于每个输入函数(此处ff和fx),然后将它们的结果相互应用.
因此,在(->) amonad中的应用意味着结果的最终参数a被分配给所有组合函数.
这就是我们所看到的 sequenceA
sequenceA [(+3),(+2),(+1)]
==
\a -> [(a + 3), (a + 2), (a + 1)]
Run Code Online (Sandbox Code Playgroud)