我正在尝试学习类型化方案/球拍(?)。下面是我的代码中的一个示例:
#lang typed/racket
(: add (Real Real -> Real))
(define (add x y)
(+ x y))
我想实现一个“检查”过程,检查运算符是否允许使用两种数据类型。例如,
(check '(+ int int))
应该导致
int
但是
(check '(* int (+ real int)))
应该会产生这样的结果:
运算符“+”必须具有相同(数字)类型的两个操作数。
也就是说,check 应该拿一个清单。
问题:
如何实现“检查”?首先,我想“好吧,我有一个列表,所以让我们使用 car 和 cdr”来获取运算符和操作数,但它不起作用,我什至不知道为什么它不起作用。我还考虑使用 if 语句 (if (and (= x y) (or (= x int) (= y int)) 等进行检查,但是......不认为这是正确的方法去吧。
我应该“添加”程序吗?还有其他方法可以做到这一点吗?在这些示例中,看起来他们只使用了“+”、“-”等。最后;如何检查输入“int”是否为 int,然后将 int 作为输出。
我现在很迷茫,我很抱歉我的问题很模糊,但如果有人能帮助我理解这一点,我会很高兴。
注意:过程 add 接受实数并输出实数,因此它不太符合示例。但我希望你能理解这个想法。谢谢:)
你问了一个有趣的问题,但它没有一个简单的答案。
您尝试编写的程序本质上是一个类型检查器。也就是说,它需要一个表达式,并检查给定函数的域是否包含调用它的参数。我们可以写其中之一,但我怀疑您会不满意。来,我现在就去写一篇......
#lang typed/racket
(require typed/rackunit)
;; a type is either
;; - 'number, or
;; - (list 'fn list-of-types type)
;; examples of types
'number
'(fn (number number) number)
(define-type FnTy (List 'fn (Listof Ty) Ty))
(define-type Ty (U 'number FnTy))
;; given an expression, returns a type
;; or signals an error
(: check (Any -> Ty))
(define (check input)
(cond [(and (list? input)
(pair? input)
(symbol? (car input)))
(define fn-ty (lookup-fn-type (car input)))
(define arg-types (map check (rest input)))
(cond [(equal? (cadr fn-ty) arg-types)
(caddr fn-ty)]
[else (error 'check
"expression didn't type-check: ~v\n"
input)])]
[(number? input)
'number]
[else (raise-argument-error
'check
"well-formed expression"
0 input)]))
(: lookup-fn-type (Symbol -> FnTy))
(define (lookup-fn-type fn-name)
(match fn-name
['+ '(fn (number number) number)]
[other (raise-argument-error 'lookup-fn-type
"known function name"
0 fn-name)]))
(define TEST-INPUT '(+ 3 43))
(check-equal? (check TEST-INPUT)
'number)
(check-equal? (check '(+ (+ 3 4) 129837))
'number)
这能回答您问题的任何部分吗?