如何在此函数中将 Traversable 类型解释为 Applicative?

How to interpret a Traversable type as an Applicative in this function?

我正在试验 haskell 类,我发现(至少一些)Traversable 数据结构也是 Applicative

当你查看 Traversable 的定义时,你会发现它可以用 sequenceA 函数定义:

sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)

并且由于 list 既是 Traversable 又是 Applicative,我确实尝试在列表列表中使用 sequenceA:

-- this thing ...
sequenceA [[0, 1], [7, 8, 9]]

-- is evaluated as [[0,7],[0,8],[0,9],[1,7],[1,8],[1,9]]

然后我得到了 2 个列表的笛卡尔积!

它甚至适用于更多的列表。


这是怎么回事?

此函数行为背后的直觉是什么?

列表应用程序的直觉是非确定性计算。您可以将具有 n 个元素的类型 [X] 的列表视为生成 X 的计算,并且它绝对是 之一该列表中包含 X 的 n 个选择,但其中任何一个都是可能的。

例如,列表 ['a','e'] 表示可以产生 'a' 或可以产生 'e' 的计算。列表 [-4,4] 可能是询问 16 的平方根的结果。列表 [] 是一个不确定的计算,无法正确产生任何值! (比如,询问 -16 的实平方根的结果...)

在这种解释中,当我们有一个函数列表 fs 和一些值 xs 时,列表 fs <*> xs 是您可以通过应用获得的所有可能结果的列表fs 中的任何函数到 xs 中的任何参数。同时,列表 pure x 是始终只产生一个结果的确定性计算,即 x.

所以!如果您有一个嵌套列表,那么有多种不同的方式来思考它的含义,包括它是一个非确定性计算的列表,或者它是一个生成列表作为结果的非确定性计算。 sequenceA 函数让您在这些表示之间转换:它接受一个非确定性计算列表并生成一个结果为列表的非确定性计算。所以:

 [[a,b,c],[d,e],[f,g,h,i]]

您可以将其视为包含三个元素的列表。第一个是 abc 之间的选择,第二个是 de 之间的选择,第三个是 de 之间的选择fghisequenceA 函数将产生一个不确定的列表选择,每个列表的形状都与上面的外部列表相同;也就是说,我们选择的每个列表的长度都是 3。第一个元素将来自 [a,b,c];第二个来自 [d,e],第三个来自 [f,g,h,i]。如果您稍微考虑一下所有可能发生的方式,您会发现这正是他们的笛卡尔积!