部分求值和柯里化

发布于 2024-10-16 23:52:40 字数 670 浏览 7 评论 0原文

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

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

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

帮助。

I have begun to understand a few examples related to currying but I am still not comfortable with the concept of currying as I would like to be. I know that currying can be used to do partial evaluation but I am not sure how it would work in certain cases.

I know how it works in the example below:

fun funkyPlus x y = x*x+y;

so let's say we only pass an argument for x then it is equivalent to the following:

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

which ends up returning

fn y => 9+y

Now, I am trying to apply this idea to the built in function foldl.

I know the code for it is:

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

My question is, what if we do not pass all the arguments to foldl (i.e. we only pass it the first argument which is the function ('a*'b->'b)). In the first example I gave, it was fairly simple to see how the function works when only one of the arguments is passed to it. However, I am having trouble seeing how foldl would work when there is only one argument passed to it.

Help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

油饼 2024-10-23 23:52:40
  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 fb [] = b|foldl fb (h::t) = Foldl ff(h,b) t;
                                                     ^^^^^
    类型冲突:类型的表达
      'a*'b
    不能有类型
      'c 列表
    

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

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

现在,回到你的问题,机器学习可以告诉我们像 foldl add 这样的表达式将具有类型 int ->;整数列表-> 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. This does not mean what you think:

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

    It defines a function which takes an argument that must be 3, and which evaluates to its RHS if it is 3 and is undefined otherwise. What you mean to say is this: If we only provide an argument for x, we have the following:

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

    and so forth.

  2. Secondly, there is an error in your 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
    

    This is because (h,b) is parsed as the third argument to foldl and not as the argument to f. Parenthesize it:

    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
    

Now, getting to your question, ML can tell us that an expression like foldl add would have type int -> int list -> int.

But in general, it may help to realize that function application is entirely mechanical. If we have these two definitions:

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

then var example = foldl add would be equivalent to this:

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

All that’s been done is that add has been substituted for f in the body of foldl, nothing more (although I have taken the liberty of replacing foldl add with example in the body).

殤城〤 2024-10-23 23:52:40

第一步是将 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

我们

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),所以 beta-reduce 为 Now 可以将其替换为它自己的定义:

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

这​​就是您所期望的,对吧?

The first step is to turn your top-level set of equations for foldl into a lambda expression which uses case analysis, like so:

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

Now you can use the same logic as before. Taking as an example the function fn (x, y) => x * y, we can see that

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

is equivalent to

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)

which beta-reduces to

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

which beta-reduces to

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

Now since we know from our first definition that prod is equivalent to foldl (fn (x, y) => x * y), we can substitute it into its own definition:

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

We can then mentally convert this back to a function defined by equations if we like:

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

That's about what you'd expect, right?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文