部分评估和讨论

时间:2011-02-12 01:44:58

标签: programming-languages recursion functional-programming sml currying

我已经开始了解一些与currying相关的例子,但我仍然不满意我想要的currying概念。我知道currying可以用来做部分评估,但我不确定它在某些情况下会起作用。

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

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如何工作。

帮助。

2 个答案:

答案 0 :(得分: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
    
  3. 现在,回答你的问题,ML可以告诉我们像foldl add这样的表达式会有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替换了f正文中的foldl,仅此而已(尽管我已经冒昧取代foldl add身体example

答案 1 :(得分: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)

beta-reduces

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

哪个beta减少到

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

这是关于你期望的,对吗?