Typed Racket:使用define-type创建泛型类型

时间:2013-06-20 20:23:19

标签: racket generic-programming typed-racket

我正试图进入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:(* x x)”。我以为我定义了一个类型,它有一个泛型类型A的参数,它返回一个泛型类型A?不会(* x x)工作吗?或者是否需要“标记”类型? (就像在C ++中一样的语言,例如列表< int>)

最重要的是:现在我的函数generate-list的类型定义的返回类型为“(Listof A)”。但是,A与ListGenFunction和ListGenLocFunction类型的参数所期望的A完全相同。但是,我想要建立这种连接,这样任何使用该函数的人都可以确定他提供的函数的类型与返回列表项的类型相匹配。

我该如何正确地做到这一点?

PS: 我不确定我是否在最后一段中描述了我的意图,以便任何人都能理解它。但是如果你采用一些通用的伪C ++代码,我想得到以下内容:

list<T> generate-list(LGF<T> f, LGLF<T> locf, int count) { ... }

所有T都完全一样。

1 个答案:

答案 0 :(得分: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))))

这就像你明确表示你正在制作(Listof A),而不仅仅是Listof