如何使用键入 scheme/racket
How to use typed scheme/racket
我正在尝试学习打字 scheme/racket(?)。下面是我的代码中的示例:
#lang typed/racket
(: add (Real Real -> Real))
(define (add x y)
(+ x y))
我想实现一个过程 "check" 来检查一个运算符是否允许使用两种数据类型。例如,
(check '(+ int int))
应该导致
int
但是
(check '(* int (+ real int)))
结果应该是这样的:
运算符“+”必须有两个相同(数字)类型的操作数。
即check应该取一个list。
问题:
如何实施 "check"?首先,我通过 "ok, I have a list, so let's use car and cdr" 获取运算符和操作数,但它不起作用,我什至不知道为什么它不起作用。我也虽然关于制作 if 语句,如 (if (and (= xy) (or (= x int) (= y int)) 等等来进行检查但是......不认为这是正确的方法去吧。
要不要做程序"add"?还有其他方法吗?在示例中,看起来他们只使用“+”、“-”等。最后;如何检查输入 "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)
这是否回答了您问题的任何部分?
我正在尝试学习打字 scheme/racket(?)。下面是我的代码中的示例:
#lang typed/racket
(: add (Real Real -> Real))
(define (add x y)
(+ x y))
我想实现一个过程 "check" 来检查一个运算符是否允许使用两种数据类型。例如,
(check '(+ int int))
应该导致
int
但是
(check '(* int (+ real int)))
结果应该是这样的:
运算符“+”必须有两个相同(数字)类型的操作数。
即check应该取一个list。
问题:
如何实施 "check"?首先,我通过 "ok, I have a list, so let's use car and cdr" 获取运算符和操作数,但它不起作用,我什至不知道为什么它不起作用。我也虽然关于制作 if 语句,如 (if (and (= xy) (or (= x int) (= y int)) 等等来进行检查但是......不认为这是正确的方法去吧。
要不要做程序"add"?还有其他方法吗?在示例中,看起来他们只使用“+”、“-”等。最后;如何检查输入 "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)
这是否回答了您问题的任何部分?