5

我已经开始理解一些与柯里化相关的例子,但我仍然对柯里化的概念感到不满意。我知道柯里化可用于进行部分评估,但我不确定它在某些情况下如何工作。

我知道它在下面的示例中是如何工作的:

fun funkyPlus x y = x*x+y;

所以假设我们只为 x 传递一个参数,那么它等价于以下内容:

fun funkyPlus 3 = (fn x => fn y => x*x+y)3

最终返回

fn y => 9+y

现在,我正在尝试将这个想法应用于内置函数foldl

我知道它的代码是:

fun foldl f b [] = b
   |foldl f b (h::t) = foldl f f(h,b) t.

我的问题是,如果我们不将所有参数传递给foldl(即我们只传递第一个参数,即函数('a*'b->'b))怎么办。在我给出的第一个例子中,当只有一个参数被传递给它时,很容易看到函数是如何工作的。foldl但是,当只有一个参数传递给它时,我很难看到它是如何工作的。

帮助。

4

2 回答 2

2
  1. 这并不意味着您的想法:

    fun funkyPlus 3 = (fn x => fn y => x*x*y)3
    

    它定义了一个函数,该函数接受一个必须为 3 的参数,如果它是 3 则计算它的 RHS,否则它是未定义的。你的意思是说:如果我们只为 x 提供一个参数,我们有以下内容:

    funkyPlus 3
    → (fn x => fn y => x*x+y) 3
    

    等等。

  2. 其次,你的有一个错误foldl

    fun foldl f b [] = b|foldl f b (h::t) = foldl f f(h,b) t;
                                                     ^^^^^
    Type clash: expression of type
      'a * 'b
    cannot have type
      'c list
    

    这是因为(h,b)被解析为 的第三个参数foldl而不是 的参数f。用括号括起来:

    fun foldl f b [] = b|foldl f b (h::t) = foldl f (f(h,b)) t;
    > val ('a, 'b) foldl = fn : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
    

现在,回答您的问题,ML 可以告诉我们 like 的表达式foldl add将具有 type int -> int list -> int

但总的来说,实现功能应用完全是机械的可能会有所帮助。如果我们有这两个定义:

fun foldl f b [] = b
  | foldl f b (h::t) = foldl f (f(h,b)) t;
add (x,y) = x + y;

那么var example = foldl add将等同于:

fun example b [] = b
  | example b (h::t) = example (h::t) (add(h,b)) t;

所做的只是在身体中add被替换了,仅此而已(尽管我冒昧地在身体中替换了)。ffoldlfoldl addexample

于 2011-02-12T02:15:52.007 回答
1

第一步是将您的顶级方程组foldl转换为使用案例分析的 lambda 表达式,如下所示:

val rec foldl = fn f => fn b => fn lst => 
  case lst of [] => b
        | (h::t) => foldl f (f(h,b)) t

现在您可以使用与以前相同的逻辑。以函数为例fn (x, y) => x * y,我们可以看到

val prod = foldl (fn (x, y) => x * y)

相当于

val prod = (fn f => fn b => fn lst => 
  case lst of [] => b
        | (h::t) => foldl f (f(h,b)) t) (fn (x, y) => x * y)

哪个β减少

val prod = fn b => fn lst => 
  case lst of [] => b
        | (h::t) => foldl (fn (x, y) => x * y) ((fn (x, y) => x * y)(h,b)) t

哪个β减少到

val prod = fn b => fn lst => 
  case lst of [] => b
        | (h::t) => foldl (fn (x, y) => x * y) (h * b) t

现在,由于我们从第一个定义中知道prod它等价于foldl (fn (x, y) => x * y),我们可以将其替换为它自己的定义:

val rec prod = fn b => fn lst => 
  case lst of [] => b
        | (h::t) => prod (h * b) t

然后,如果我们愿意,我们可以在心理上将其转换回由方程式定义的函数:

fun prod b [] = b
  | prod b (h::t) = prod (h * b) t

这就是你所期望的,对吧?

于 2011-02-12T02:33:22.553 回答