最外层评估如何在应用咖喱函数时起作用?

时间:2019-07-14 13:32:34

标签: haskell functional-programming evaluation currying

mult被定义为咖喱函数:

mult    ::  Int ->  Int ->  Int
mult    x   =   \y  ->  x   *   y

mult (1+2) (2+3)中,

  • 什么是redex。它们是mult(1+2)1+22+3吗?
  • 最外面的redex是什么,它是2+3吗?

根据赫顿(Hutton)在《 Haskell编程》中的描述,最内层的评估对表达式进行如下操作:

mult    (1+2)   (2+3)
= { applying    the first   +   }
mult    3   (2+3)
= { applying    mult    }
(\y ->  3   *   y)  (2+3)
= { applying    +   }
(\y ->  3   *   y)  5
= { applying    the lambda  }
3   *   5
= { applying    *   }
15

mult (1+2) (2+3)的最外部评估如何工作? 最外面的评估工作如下吗?

mult (1+2) (2+3)
= mult (1+2) 5
= (\y -> (1+2) * y) 5
= (1+2) * 5  // Is (1+2) evaluated before (1+2) * 5, because builtin function "*" is strict, i.e. application of builtin function always happen after evaluation of its args?
= 3*5
= 15

谢谢。

2 个答案:

答案 0 :(得分:1)

mult (1+2) (2+3)中最外面的redex,即

          mult
       /        \
      +          +
    1   2      2   3

mult x y,其中x = (1+2)y = (2+3)

有两个内部Redex,(1+2)(2+3)。因此,最里面的最左端的redex是(1+2)

通过最左边的redex进行还原的过程如下:

mult (1+2) (2+3)
=
mult 3 (2+3)
=
mult 3 5
= {- mult x = \y -> x * y -}
(let x = 3 in (\y -> x * y)) 5
=
let x = 3 in let y = 5 in x * y
=
3 * 5
=
15

减少最高的redex的过程如下:

mult (1+2) (2+3)
= {- mult x = \y -> x * y -}
(let x = (1+2) in (\y -> x * y)) (2+3)
=
let x = (1+2) in let y = (2+3) in x * y
=
(1+2) * (2+3)
=
3 * (2+3)
=
3 * 5
=
15

答案 1 :(得分:1)

写下分析树:

         o
       /   \
     o       o
    / \     /|\
mult   o   2 + 3
      /|\
     1 + 2

(为简单起见,我将二进制中缀+运算符视为单个应用程序,也可能是((+) 1) 2

现在最外层的函数应用程序是mult (1+2)到参数2+3的函数,但是由于函数不是单个值而是应用程序本身,因此它不可简化。我们必须先对此进行评估:

(mult (1+2)) (2+3)
((\x->\y->x*y) (1+2)) (2+3) -- the value that `mult` refers to
(\y->(1+2)*y) (2+3) -- evaluate the application of `\x->`

现在我们可以评估根函数应用程序了:

(1+2) * (2+3) -- application of `\y->`

现在最外面的表达式是*,但是您知道这些整数运算符很严格,因此它们需要首先评估其参数(从左到右,IIRC):

3 * (2+3)
3 * 5
15