我正在尝试对 Typed Racket 有所了解,但在让(诚然相当构建的)实验工作时遇到了一些麻烦。
这是我最初拥有的:
#lang typed/racket
(: generate-list
(All (A)
((A -> A) (Integer -> A) Integer -> (Listof A))))
(define (generate-list function location-function num-items)
(let: loop : (Listof A)
((count : Integer 0)
(result : (Listof A) (list)))
(if (>= count num-items)
(reverse result)
(loop (+ count 1)
(cons (function (location-function count)) result)))))
; ---------------------------------
(: f (Number -> Number))
(define (f x) (* x x))
(: locf (Integer -> Number))
(define (locf x) x)
; ---------------------------------
(displayln (generate-list f locf 10))
哪个有输出:
(0 1 4 9 16 25 36 49 64 81)
这很好。然后我想我可以通过给函数和位置函数一个定义的类型来更好地记录这一点:
#lang typed/racket
(define-type (ListGenFunction A) (A -> A))
(define-type (ListGenLocFunction A) (Integer -> A))
(: generate-list
(All (A)
(ListGenFunction ListGenLocFunction Integer -> (Listof A))))
(define (generate-list function location-function num-items)
(let: loop : (Listof A)
((count : Integer 0)
(result : (Listof A) (list)))
(if (>= count num-items)
(reverse result)
(loop (+ count 1)
(cons (function (location-function count)) result)))))
; ----------- Numbers! ------------
(: f ListGenFunction)
(define (f x) (* x x))
(: locf ListGenLocFunction)
(define (locf x) x)
; ---------------------------------
(displayln (generate-list f locf 10))
现在问题就从这里开始了(我真的希望一些有经验的 Typed Racketeers 现在不会太用力)。一方面,类型检查器在我定义 f 的那一行给了我一个错误。该消息相当冗长,但基本上是:“类型检查器:函数应用程序中没有匹配的函数域:类型:... in:(* xx)”。我以为我定义了一个类型,它有一个泛型类型 A 的参数,它返回泛型类型 A?(* xx) 不行吗?或者是否需要“标记”类型?(例如在类似 C++ 的语言中,它是 list<int>)
最重要的是:现在我对函数 generate-list 的类型定义的返回类型为“(Listof A)”。但是 A 根本没有被声明为与 ListGenFunction 和 ListGenLocFunction 类型的参数所期望的 A 相同。但是,我有点想建立这种联系,以便使用该函数的任何人都可以确保他提供的函数的类型与返回的列表项的类型相匹配。
我该如何正确地做到这一点?
PS:我不确定我是否在最后一段中描述了我的意图,以便任何人都能理解。但是,如果您采用一些通用的伪 C++ 类代码,我想得到以下内容:
list<T> generate-list(LGF<T> f, LGLF<T> locf, int count) { ... }
所以所有的T都完全相同。