带有 4 个参数的文件夹?

use*_*476 2 haskell

我很难理解为什么这段代码取自haskell.org 练习页面类型检查 (并用作列表反转功能):

myReverse :: [a] -> [a]
myReverse xs = foldr (\x fId empty -> fId (x : empty)) id xs []
Run Code Online (Sandbox Code Playgroud)

我的第一个困惑点是 foldr 接受 3 个参数,而不是 4 个:

foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
Run Code Online (Sandbox Code Playgroud)

所以我猜这myReverse相当于:

myReverse xs = foldr ((\x fId empty -> fId (x : empty)) id) xs []
Run Code Online (Sandbox Code Playgroud)

但是这也不应该起作用,因为在 lambda 中,它x是一个列表元素而不是一个函数......

n. *_* m. 5

这么想吧。每个函数只接受一个参数。它可能返回另一个函数(接受一个参数)。看起来像多参数调用的东西

f a b c
Run Code Online (Sandbox Code Playgroud)

实际上被解析为

((f a) b) c
Run Code Online (Sandbox Code Playgroud)

也就是说,一个单参数函数应用程序链。函数类型

f :: a -> b -> c -> d
Run Code Online (Sandbox Code Playgroud)

可以分解为

f :: a -> (b -> (c -> d))
Run Code Online (Sandbox Code Playgroud)

即一个函数返回一个函数返回一个函数。我们通常认为它是三个参数的函数。但它可以接受三个以上吗?是的,如果d碰巧是另一种函数类型。

这正是您的fold示例所发生的情况。您作为第一个参数传递给的函数foldr接受三个参数,这与接受两个参数并返回另一个函数完全相同。现在(简化)类型foldr

(a -> b -> b) -> b -> [a] -> b
Run Code Online (Sandbox Code Playgroud)

但是如果你查看它的第一个参数,你会发现它是一个包含三个参数的函数。正如我们所见,这与添加两个参数并返回一个函数的函数完全相同。所以b恰好是一个函数类型。由于b还返回tuoe的foldr当应用于三个参数

foldr (\x fId empty -> fId (x : empty)) id
Run Code Online (Sandbox Code Playgroud)

它是一个函数,现在可以应用于另一个参数

(foldr (\x fId empty -> fId (x : empty)) id xs) []
Run Code Online (Sandbox Code Playgroud)

我让你弄清楚究竟b是什么。