最外层评估如何在柯里化函数的应用程序上工作?

How does outermost evaluation work on an application of a curried function?

mult 定义为柯里化函数:

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

mult (1+2) (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

谢谢。

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

          mult
       /        \
      +          +
    1   2      2   3

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

有两个内部索引,(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

写下解析树:

         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->`

现在最外层的表达式是 *,但如您所知,这些整数运算符是严格的,因此它们需要先计算其参数 (left-to-right, IIRC):

3 * (2+3)
3 * 5
15