这从sequenceA的类型可以看出:
sequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a)
参数的外部类型必须是Traverable
,其内部类型必须是Applicative
.
现在,当你给sequenceA一个函数列表时(Num a) => [a -> a]
该列表将是Traversable
,列表中的内容应该是Applicative
。因此,它使用函数的应用实例。
所以当你将sequenceA应用到[(+3),(+2),(+1)]
,建立以下计算:
sequenceA [(+3),(+2),(+1)] = (:) <$> (+3) <*> sequenceA [(+2),(+1)]
sequenceA [(+2),(+1)] = (:) <$> (+2) <*> sequenceA [(+1)]
sequenceA [(+1)] = (:) <$> (+1) <*> sequenceA []
sequenceA [] = pure []
让我们看看最后一行。pure []
获取一个空列表并将其放入某个应用结构中。正如我们刚刚看到的,本例中的应用结构是((->) r)
。因为这,sequenceA [] = pure [] = const []
.
现在,第 3 行可以写为:
sequenceA [(+1)] = (:) <$> (+1) <*> const []
以这种方式组合功能<$>
and <*>
并行应用的结果。(+1)
and const []
都应用于同一个参数,并且使用以下方法组合结果(:)
所以sequenceA [(+1)]
返回一个函数,该函数接受一个Num a => a
类型值,适用(+1)
到它,然后将结果添加到一个空列表中,\x -> (:) ((1+) x) (const [] x)
= \x -> [(+1) x]
.
这个概念可以进一步延伸到sequenceA [(+3), (+2), (+1)]
。它产生一个函数,该函数接受一个参数,将所有三个函数应用于该参数,并将三个结果与(:)
将它们收集在一个列表中:\x -> [(+3) x, (+2) x, (+1) x]
.