4

我正在尝试对 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都完全相同。

4

1 回答 1

3

这里有两个问题,都源于同样的困惑。您使用的是泛型类型 ,ListGenFunction而没有告诉 Typed Racket(或您的程序的读者)您正在使用它的特定类型。

例如,f不是一个任意 ListGenFunction的,它是一个ListGenFunction专门用于数字的。所以你应该写:

(: f (ListGenFunction Integer))

(: locf (ListGenLocFunction Integer))

同样,您应该给出generate-list这样的类型:

(: generate-list
   (All (A)
     ((ListGenFunction A) (ListGenLocFunction A) Integer -> (Listof A))))

这就像您明确地说您正在生产 a (Listof A),而不仅仅是 a Listof

于 2013-06-21T14:25:29.137 回答