【问题标题】:What is the difference between these two type annotation and why they are different?这两种类型注释有什么区别,为什么它们不同?
【发布时间】:2019-12-02 03:05:06
【问题描述】:

我试图从 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)))))

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

【问题讨论】:

    标签: types racket typed-racket


    【解决方案1】:

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

    (: 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-type 并且 a(cdr l) 提供信息时找出 ((rember-fc test?) a (cdr l)) 中的 forall-variable 是什么。如果 forall 在中间,则内部应用程序不需要类型推断,而外部应用程序类型推断成功,因为外部应用程序参数提供了信息。

    但是,当rember-fc 具有forall-type 并且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)))]))))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-12
      • 1970-01-01
      • 2011-12-08
      • 2016-04-18
      • 2013-09-08
      • 2019-12-11
      • 2019-03-31
      • 2020-01-22
      相关资源
      最近更新 更多