我想定义一个这样的函数:
(define (((lift fn) . gs) . args)
(apply fn (map (lambda (g) (apply g args)) gs)))
这基本上是#34;升降机"函数fn
使得它不接受正常参数,而是接受函数并生成一个新函数。所以,例如,
(define add (lift +))
(define sum-of-sin-and-cos (add sin cos))
(sum-of-sin-and-cos 5) ; is equivalent to (+ (sin 5) (cos 5))
(define sum-of-multiplication-and-division (add * /))
(sum-of-multiplication-and-division 1 2 3 4 5) ; is equivalent to (+ (* 1 2 3 4 5) (/ 1 2 3 4 5))
这适用于普通的Racket。现在,我想将此功能移动到键入的球拍中。这是我提出的类型声明:
(: lift (All (A ... ) (All (B ...) (All (C)
((B ... B -> C) ->
((A -> B) ... B ->
(A ... B -> C)))))))
以下是我认为定义所说的内容:适用于所有类型A0
,A1
,... An
和B0
,{{ 1}},... B1
和Bn
:
C
将(lift
,B0
,... B1
的函数转换为Bn
并生成:C
到Ai
,Bi
从0到i
),它反过来产生:n
,Ai
从0到i
的函数,反过来生成:n
这不起作用:在最后一行C
我得到(A ... B -> C)
。
这不是我使用Typed Racket时省略号的第一个问题,而且我认为这实际上是对省略号意图做什么的基本误解。
作为旁注,如果我尝试将Type Checker: Type variable A must be used with ... in: A
条款折叠为这样的单个条款:
All
然后在第二行(All (A ... B ... C) blah blah blah)
我收到以下错误:((B ... B - C) ->
(指的是该行的第二行)。我也不太了解。
答案 0 :(得分:5)
首先回答你的上一个问题,All
的类型语法不允许同时绑定多个虚线变量,因为不清楚如何实例化它们。这与您在同一函数中不能有多个休息参数的原因相同。
关于lift
,我认为你想要的类型是:
(: lift (All (C A ...)
(All (B ...)
((B ... B -> C)
->
((A ... A -> B) ... B
->
(A ... A -> C))))))
然后该函数通过一个注释:
(define (((lift fn) . gs) . args)
(apply fn (map
(λ: ([g : (A ... A -> B)])
(apply g args))
gs)))
由于嵌套的foralls,使用此函数需要一些显式注释;这是你的测试用例:
(define add ((inst (inst lift Number Number) Number Number) +))
(define add2 ((inst (inst lift Number Number Number Number Number Number)
Number Number)
+))
(define sum-of-sin-and-cos (add sin cos))
(sum-of-sin-and-cos 5) ; is equivalent to (+ (sin 5) (cos 5))
(define sum-of-multiplication-and-division (add2 * /))
(sum-of-multiplication-and-division 1 2 3 4 5)
请注意,我必须为add2
创建单独的绑定,因为它们用于不同的类型。