您应该如何在Typed Racket中的letrec中键入相互注释的递归函数?

时间:2018-11-14 16:47:46

标签: typed-racket

如果我正确理解,这是注释类型化球拍letrec中定义的函数的正确方法:

#lang typed/racket

(letrec ((is-even? (lambda ((n : Nonnegative-Integer))
                     : Boolean
                     (or (zero? n)
                         (is-odd? (sub1 n)))))
         (is-odd? (lambda ((n : Nonnegative-Integer))
                    : Boolean
                    (and (not (zero? n))
                         (is-even? (sub1 n))))))
  (is-odd? 11))

但是这会给出错误消息:

Type Checker: insufficient type information to typecheck. please add more
              type annotations in: is-odd?

一种解决方法是:

(local ((: is-even? : Nonnegative-Integer -> Boolean)
        (define (is-even? n)
          (or (zero? n)
              (is-odd? (sub1 n))))
        (: is-odd? : Nonnegative-Integer -> Boolean)
        (define (is-odd? n)
          (and (not (zero? n))
               (is-even? (sub1 n)))))
  (is-odd? 11))

也可以使用诸如this question之类的传统表示法形式,但是我希望也能够使用当前的表示法来对letrec进行注释。

1 个答案:

答案 0 :(得分:0)

您可以在letrec中的函数名称之后添加类型注释,如下所示:

(letrec ([f1 : type1 expr1]
         [f2 : type2 expr2])
  body)

以您的示例为例,

(letrec ([is-even? : (-> Nonnegative-Integer Boolean)
                   (lambda (n)
                     (or (zero? n)
                         (is-odd? (sub1 n))))]
         [is-odd? : (-> Nonnegative-Integer Boolean)
                  (lambda (n)
                    (and (not (zero? n))
                         (is-even? (sub1 n))))])
  (is-odd? 11))

为什么这样做有效,但是不能在lambda中放入类型注释?

这是因为确保每个lambda类型检查分别依赖于is-odd?is-even?的类型。但是,如果您不直接注释函数名,则只能尝试通过对lambda进行类型检查来推断这些类型。

直接注释函数名称意味着它甚至不必知道is-even?is-odd?必须具有什么类型就可以查看lambda。