方案中的咖喱

问题描述 投票:0回答:5

我有这个

curry
功能:

(define curry
(lambda (f) (lambda (a) (lambda (b) (f a b)))))

我认为这就像

(define curry (f a b))

我的作业是使用

consElem2All
编写一个函数
curry
,其工作原理应该像

(((consElem2All cons) 'b) '((1) (2 3) (4)))
>((b 1) (b 2 3) (b 4))

我已经按照常规方式编写了这个函数:

(define (consElem2All0 x lst) 
  (map (lambda (elem) (cons x elem)) lst))

但还是不知道如何用

curry
来改造它。有人可以帮助我吗?

提前致谢

熊克

scheme currying
5个回答
4
投票

您应该首先阅读有关柯里化的内容。如果你不明白咖喱是什么,可能真的很难使用它......就你而言,http://www.engr.uconn.edu/~jeffm/Papers/curry.html可能是一个好的开始。

柯里化的一个非常常见和有趣的用途是使用像reduce或map这样的函数(对于它们自己或它们的参数)。

让我们定义两个柯里化运算符!

(define curry2 (lambda (f) (lambda (arg1) (lambda (arg2) (f arg1 arg2)))))
(define curry3 (lambda (f) (lambda (arg1) (lambda (arg2) (lambda (arg3) (f arg1 arg2 arg3))))))

然后是一些柯里化的数学函数:

(define mult (curry2 *))
(define double (mult 2))

(define add (curry2 +))
(define increment (add 1))
(define decrement (add -1))

然后是柯里化的reduce/map:

(define creduce (curry3 reduce))
(define cmap (curry2 map))

使用它们

首先减少用例:

(define sum ((creduce +) 0))
(sum '(1 2 3 4)) ; => 10

(define product (creduce * 1))
(product '(1 2 3 4)) ; => 24

然后映射用例:

(define doubles (cmap double))
(doubles '(1 2 3 4)) ; => (2 4 6 8)

(define bump (cmap increment))
(bump '(1 2 3 4)) ; => (2 3 4 5)

我希望能帮助您掌握柯里化的用处...


1
投票

所以你的 curry 版本采用带有两个参数的函数,比方说:

(define (cons a b) ...)

并将其变成可以这样称呼的东西:

(define my-cons (curry cons))
((my-cons 'a) '(b c)) ; => (cons 'a '(b c)) => '(a b c)

您实际上有一个需要三个参数的函数。如果您有一个管理 3 元函数的

curry3
,您可以执行以下操作:

(define (consElem2All0 the-conser x lst) ...)

(就像你所做的那样,但允许使用除 cons 之外的类似 cons 的函数!)

然后这样做:

(define consElem2All (curry3 consElem2All0))

你手头没有这样的

curry3
。因此,您可以构建一个,或者通过自己“手动”柯里化额外变量来解决它。解决它看起来像:

(define (consElem2All0 the-conser)
  (lambda (x lst) ...something using the-conser...))
(define (consElem2All the-conser)
  (curry (consElem2All0 the-conser)))

请注意,map 表达式本身还有另一种可能的 curry 用途,即通过将 lambda 包裹在 cons 周围以将元素传递给 cons 来暗示。如何将

x
柯里化为
cons
以便获得可直接用于映射的单参数函数?...


0
投票

也许最好使用通用版本:

(define (my-curry f)
  (lambda args
    (cond ((= (length args) 1)
             (lambda lst (apply f (cons (car args) lst))))
          ((>= (length args) 2)
             (apply f (cons (car args) (cdr args)))))))

0
投票

我的任务是使用 curry 编写一个函数 consElem2All...

如果您从字面上理解这部分(忘记原始句子的第二部分),则意味着您应该在实现的主体中使用柯里化函数。

...应该像...

一样工作

我认为你自己添加了第二部分,这增加了你的困惑。

很多时候,人们所说的柯里化实际上是偏函数应用。因此,在下面的解决方案中,我没有调用

curry
curry
,而是调用
partial

(define (partial f . args)
  (lambda more-args
    (apply f (append args more-args))))

(define (cons-elem-to-all elem lst)
  (map (partial cons elem) lst))

我很确定,这就是你的老师正在寻找的东西。

> (cons-elem-to-all 'b '((1) (2 3) (4)))
((b 1) (b 2 3) (b 4))

-2
投票
(define (consElem2All0 x lst) 
  (map ((curry cons) x) lst))
© www.soinside.com 2019 - 2024. All rights reserved.