这怎么让表达起作用?

时间:2018-01-19 15:06:10

标签: haskell lambda anonymous-function let expression-evaluation

鉴于这一行Haskell代码,我的任务是将其评估为最简单的形式。

let g h k = (\x -> k (h x)) in g (+1) (\x -> x+x) 20

我已经得到了答案(当然在GHCI中自己评估过):42

但是,我想更好地了解评估在这里的实际运作方式。一般来说,我想我知道如何(简单)让表达式起作用:

实施例

a = let y = 5 in y * 5  -- a == 25

此评估结果为25,因为我们将y绑定到5的值,a被赋值为y*5的值(后面的部分) in)。绑定y = 5仅在let范围内有效。

到目前为止,唯一的解释(至少评估为42)如下:

let g h k = (\x -> k (h x)) in g (+1) (\x -> x+x) 20
  • g(\x -> k (h x))
  • h(+1)(函数(\x -> x+1)
  • k(\x -> x+x)

    1. 20g的输入,产生k (h 20)
    2. h 20提供20 + 1 = 21
    3. k (h 20) = k 21 = 21 + 21 = 42

但令我困惑的是在let之后使用g h k。这是什么意思?

2 个答案:

答案 0 :(得分:10)

考虑一个函数定义。如果你写:

g h k x = k (h x)

然后它是一个函数,它接受三个参数hkx并返回k (h x)。这相当于:

g h k = \x -> k (h x)

或:

g h = \k x -> k (h x)

或:

g = \h k x -> k (h x)

因此我们可以在函数的头部和body中的lambda表达式之间传递变量。实际上,Haskell编译器会重写它。

因此,使用let表达式,我们定义了一个局部范围的函数,就像上面定义的那样。现在,如果我们拨打g (+1) (\x -> x+x) 20,则会gh = (+1)k = (\x -> x+x)致电x = 20

所以我们将其评估为:

(\x -> x+x) ((+1) 20)

评估为:

   (\x -> x+x) ((+1) 20)
-> ((+1) 20)+((+1) 20)
-> 21 + 21
-> 42

答案 1 :(得分:8)

g h k = ...是一个函数定义。这意味着将g应用于两个参数(名为hk)的结果将计算为...部分。换句话说,它是g = \h -> \k -> ...的捷径。

因此我们可以按步骤简化表达式:

let g h k = (\x -> k (h x)) in g (+1) (\x -> x+x) 20
let g = \h -> \k -> (\x -> k (h x)) in g (+1) (\x -> x+x) 20
(\h -> \k -> (\x -> k (h x))) (+1) (\x -> x+x) 20
(\k -> (\x -> k ((+1) x))) (\x -> x+x) 20
(\x -> (\x -> x+x) ((+1) x)) 20
(\x -> x+x) ((+1) 20)
(\x -> x+x) 21
21 + 21
42