haskell - Haskell 中高阶函数的 Lambda 表达式
问题描述
在这本书之后,Haskell 中的一切都是-λ
演算:函数 likef(x)=x+1
可以在 Haskell 中写为f = \x -> x+1
和 ,λ
表达式为λx.x+1
。
λ
高阶函数的表达式是什么map::(a -> b) -> [a] -> [b]
?还是λ
函数的表达式($) :: (a -> b) -> a -> b
?- 函数列表(即。
f::[a->b]
)呢?一个具体的例子可以是h = map (\f x -> f x 5) [(-),(+)]
。那么λ
符号就像h = map (λfx.f(x(5)) [(λab.a-b),(λab.a+b)]
?
我只熟悉 alpha 转换、beta 减少等过程,但如果您按 λ
术语分解函数列表,那将不胜感激,无需简化。
谢谢。
解决方案
首先,
Haskell 中的一切都是 λ-演算
这并不正确。Haskell 有许多与无类型 λ 演算中的东西不对应的特性。也许他们的意思是它可以编译为 λ-演算,但这很明显,“任何图灵完备的语言......” jadda jadda。
什么是高阶函数的 λ 表达式,例如
map :: (a -> b) -> [a] -> [b]
这里有两个不相关的问题。对于直接 λ 转换,“高阶函数”部分完全没有问题,正如评论已经说过的那样
($) = \f -> \x -> f x -- λf.λx.fx
或者
($) = \f x -> f x
($) = \f -> f -- by η-reduction
(在 Haskell 中我们将进一步缩短为($) = id
)。
另一件事是map
在代数数据类型上定义的递归函数,将其转换为无类型的 λ 演算将导致我们与 Haskell 相去甚远。将其翻译成包含模式case
匹配let
(很容易想出
map = \f l -> case l of
[] -> []
(x:xs) -> f x : map f xs
...或避免在顶级绑定上递归
map = \f -> let go l = case l of
[] -> []
(x:xs) -> f x : go xs
in go
我们无法摆脱let
这种情况,因为 λ 演算不直接支持递归。但是递归也可以用定点组合器来表示;与无类型 λ 演算不同,我们不能自己定义 Y 组合子,但我们可以假设fix :: (a -> a) -> a
为原语。结果证明它完成了与递归 let-binding 几乎完全相同的工作,然后立即对其进行评估:
map = \f -> fix ( \go l -> case l of
[] -> []
(x:xs) -> f x : go xs )
为了为此构建一个 λ 风格的语法,
map = λ f .fix(λ g .λ l .{ l ? []⟼[]; ( x : s )⟼<i>fx: gs })
推荐阅读
- html - 当新数据进入时,如何获取要更新的 html 元素?
- javascript - 如何使用 leader-line js 在 Swiper 幻灯片之间制作动画线条?
- nginx - Nginx 不代理 css js 字体文件(总是返回 index.html)
- excel - 在日期范围内查找日期VBA excel
- http - 可以有条件地转发或终止传入 TLS 连接的 Go 服务器
- ldap - 是否可以仅使用 LDAP 选择用户帐户数据?
- spring-boot - 2 个分支中的 1 个错过了 jacooco stream().filter
- php - 将 Json 文件加载到表时结果不一致
- nginx - 如何获取 nginx 上游返回的“Set-Cookie”标头中所有 cookie 的内容
- android - 如何在 Jetpack Compose 中使用 Coil 显示自定义可组合占位符?