首页 文章

部分评估和讨论

提问于
浏览
4

我已经开始了解一些与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 回答

  • 2
    • 这并不意味着你的想法:
    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
    

    等等 .

    • 其次, 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可以告诉我们像 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 已经在 foldl 的正文中替换了 f ,仅此而已(尽管我已经冒昧地用身体中的 example 替换 foldl add ) .

  • 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
    

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

相关问题