2013-06-20 221 views
3

我試圖讓類型球拍有點兒成型,但是我在嘗試工作時遇到了一些麻煩。類型球拍:使用定義類型創建通用類型

這是我本來有:

#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)) 

現在,這裏的問題開始的地方(我真的希望一些有經驗的類型化詐騙者不facepalming太現在很難)。首先,類型檢查器在我定義f的行上給我一個錯誤。該消息相當長,但基本上是:「類型檢查器:功能應用程序中沒有匹配的功能域:類型:... in:(* x x)」。我以爲我定義了一個類型,它有一個返回泛型類型A的泛型類型A的參數?不會(* x x)工作嗎?或者是否需要「標記」類型? (例如在C++語言中,例如列表<int>)

最重要的是:現在我的函數generate-list的類型定義具有返回類型「(ListofA)」。但是A並沒有被聲明爲與ListGenFunction和ListGenLocFunction類型的參數期望的A相同。然而,我想要建立這種連接,以便任何使用該功能的人都能確保他提供的功能類型與返回列表項的類型相匹配。

如何正確執行此操作?

PS: 我不確定我是否在最後一段描述了我的意圖,以便任何人都能理解它。但是,如果你需要一些通用的僞C++ - 代碼一樣,我希望得到以下幾點:

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

讓所有T的是完全一樣的。

回答

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

+0

啊,所以我可以(也必須)標記類型!感謝您解決這個問題!現在程序執行併產生正確的結果。 DrRacket(Windows,第5版)3.3)顯示錯誤 「類型檢查器:在宏擴展錯誤 - 不是有效的類型:(A)在:(限定型(ListGenFunction A)(A - > A))」。你知道爲什麼會顯示這個錯誤嗎?由於程序基本上正常工作,這是否爲假? – cronotk

+0

好的,版本5.2.1(在Debian中)沒有這個問題。我想這是5.3.x中的一個小錯誤,或者是一般的Windows版本。 – cronotk

+0

按「運行」時是否顯示此錯誤?或者別的地方? –