如果我正确理解,这是注释类型化球拍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
进行注释。
答案 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。