我很难理解为什么这段代码取自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是一个列表元素而不是一个函数......
这么想吧。每个函数只接受一个参数。它可能返回另一个函数(接受一个参数)。看起来像多参数调用的东西
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是什么。
| 归档时间: |
|
| 查看次数: |
492 次 |
| 最近记录: |