这两种类型注释有什么区别,为什么不同?

What is the difference between these two type annotation and why they are different?

我正在尝试为 Little Schemer 一书中的此函数添加类型。

(define rember-fc
  (λ(test?)
    (λ (a l)
      (cond [(null? l) '()]
            [(test? a (car l)) (cdr l)]
            [else
             (cons (car l)
                   ((rember-fc test?) a (cdr l)))]))))

这种类型会导致错误。

(: rember-fc  (∀ (a) (-> (-> Any Any Boolean)  (-> a (Listof a) (Listof a)))))

这种类型有效。

(: rember-fc  (-> (-> Any Any Boolean)  (∀ (a) (-> a (Listof a) (Listof a)))))

我想知道为什么这两种类型会导致不同的结果,有什么区别?

该函数可以在第一个版本的类型签名下工作

(: rember-fc  (∀ (a) (-> (-> Any Any Boolean)  (-> a (Listof a) (Listof a)))))

如果在递归调用中使用函数的地方添加注解,替换

((rember-fc test?) a (cdr l))

(((inst rember-fc a) test?) a (cdr l))

其中 inst 类型注释允许它进行类型检查。

这个函数的使用有两个应用,一个内部应用,一个外部应用。内部应用程序首先进行类型检查,只有当外部应用程序具有内部应用程序的具体类型后才会进行类型检查。

Typed Racket 的类型推断算法足够聪明,可以在 (rember-fc test?) 具有 forall 类型且 a 和 [=19= 时找出 ((rember-fc test?) a (cdr l)) 中的 forall 变量是什么] 提供资料。如果forall在中间,则内部应用程序不需要类型推断,并且外部应用程序类型推断成功,因为外部应用程序参数提供了信息。

然而,类型推断不够智能,无法在 rember-fc 具有 forall 类型时弄清楚这一点,并且 test? 没有在内部应用程序中提供信息。 a(cdr l) 仅稍后在外部应用程序中应用。当类型推断猜不出来的时候,在内层应用中猜测Any,后来在外层应用中才发现猜错了

所以两个工作版本是:

(: rember-fc  (∀ (a) (-> (-> Any Any Boolean)  (-> a (Listof a) (Listof a)))))
(define rember-fc
  (λ (test?)
    (λ (a l)
      (cond [(null? l) '()]
            [(test? a (car l)) (cdr l)]
            [else
             (cons (car l)
                   (((inst rember-fc a) test?) a (cdr l)))]))))

并且:

(: rember-fc  (-> (-> Any Any Boolean)  (∀ (a) (-> a (Listof a) (Listof a)))))
(define rember-fc
  (λ (test?)
    (λ (a l)
      (cond [(null? l) '()]
            [(test? a (car l)) (cdr l)]
            [else
             (cons (car l)
                   ((rember-fc test?) a (cdr l)))]))))