ham*_*rns 3 lambda haskell function
我目前正在修订 Haskell 中 lambda 表达式的章节(\\)。只是想知道是否有人可以帮忙解释一下这是怎么做到的:
const :: a \xe2\x86\x92 b \xe2\x86\x92 a \nconst x _ = x (this part)\nRun Code Online (Sandbox Code Playgroud)\n定义如下:
\nconst :: a \xe2\x86\x92 (b \xe2\x86\x92 a) \nconst x = \xce\xbb_ \xe2\x86\x92 x (how did it become like this?)\nRun Code Online (Sandbox Code Playgroud)\n
签名a -> b -> a和 的解析a -> (b -> a)方式完全相同,就像算术表达式1 - 2 - 3和(1 - 2) - 3一样:->运算符是右关联的,而-运算符是左关联的,即如果没有明确指定,解析器会有效地将括号放在正确的位置。换句话说,A -> B -> C被定义为 A -> (B -> C)。
如果我们明确地写成a -> (b -> a),那么我们这样做是为了把重点放在我们正在处理柯里化函数的事实上,即我们可以逐一接受参数而不是一次接受所有参数,但Haskell 中的所有多参数函数无论如何都是咖喱。
至于为什么const x _ = x和const x = \_ -> x是等价的:首先,迂腐地说它们并不等价,请参阅这个答案的底部。但现在我们先忽略这一点。
lambda 表达式和(单)函数子句都只是定义函数的方式。喜欢,
sqPl1 :: Int -> Int
sqPl1 x = x^2 + 1
Run Code Online (Sandbox Code Playgroud)
做同样的事情
sqPl1 = \x -> x^2 + 1
Run Code Online (Sandbox Code Playgroud)
这只是一种不同的语法。有些人会说这个f x = ...符号只是xlambda 中绑定的语法糖f = \x -> ...,因为 Haskell 基于 lambda 演算,而在 lambda 演算中 lambda 是编写函数的唯一方法。(不过,这有点过于简单化了。)
我说它们并不完全等同。我在这里指的是两件事:
您可以拥有其范围比参数绑定更持久的本地定义。例如,如果我写
foo x y = ec * y
where ec = {- expensive computation depending on `x` -}
Run Code Online (Sandbox Code Playgroud)
每当应用时, thenec总是从头开始计算。foo但是,如果我把它写成
foo x = \y -> ec * y
where ec = {- expensive computation depending on `x` -}
Run Code Online (Sandbox Code Playgroud)
然后我可以部分应用于 foo一个参数,并且可以使用许多不同的值来评估生成的单参数函数,y而无需ec再次计算。例如,map (foo 3) [0..90]使用 lambda 定义会更快。(另一方面,如果存储的值占用大量内存,最好不要保留它;这取决于情况。)
Haskell 有一个恒定应用形式的概念。这是一个微妙的主题,我不会在这里讨论,但它可能会受到您是否将函数编写为 lambda、使用子句或扩展参数的影响。