2012-03-04 51 views
3

讓兩人變量類型:如何處理多態變體列表?

type typeA = 
    | A1 
    | A2 
;; 

type typeB = 
    | B1 of typeA 
    | B2 of typeA 
;; 

和類型檢查功能:

let isA1 = function A1 -> true | _ -> false;; 
let isA2 = function A2 -> true | _ -> false;; 
let isB1 = function B1 e -> true | _ -> false;; 
let isB2 = function B2 e -> true | _ -> false;; 

我想創建的那些功能的列表來檢查A型或B

的元素因爲它們是不同類型的,所以我需要多態變體,並且我得到:

type filterA = 
{ 
    handleA : typeA -> bool; 
};; 

type filterB = 
{ 
    handleB : typeB -> bool; 
};; 

type filterslist = [`FilterA of filterA | `FilterB of filterB] list ;; 

let filters1 = [`FilterA { handleA = isA1 }; `FilterB { handleB = isB1 }] ;; 

所以現在我要遍歷filters1檢查參數 我試過的類型:

let exec_filters filters event = List.iter (fun fil -> match fil with `FilterA -> fil.handleA event;()| `FilterB -> fil.handleB event;()) filters;; 

,但它不是讚賞:

Error: This expression has type [< `FilterA | `FilterB ] 
     but an expression was expected of type filterA 

我該如何處理呢?

+5

「因爲它們是不同類型的,我需要多態變體」 - 不。如果你給我們提供與你合作的真實東西,我們可以更好地幫助你,但看起來你正在爲自己創造更多的工作。 – Ashe 2012-03-05 01:43:19

回答

5

您正在使用類似於Scheme或instanceOf的「類型檢查謂詞」這一事實表明您的代碼可能存在某些錯誤。 OCaml是一種靜態類型的語言,你不應該:

iterate over filters1 to check the type of the argument I tried

你爲什麼這樣做?如果你想要處理多種類型,那麼做的方式就是使用多態。多態變體可能對此有所幫助,但我仍然不相信您的代碼不是以一種奇怪的方式編寫的。

+0

實際上,我試圖獲得一種運行時的「動態」模式匹配,所以是的我想處理多種類型,每一個觸發的特定功能 – codablank1 2012-03-04 22:33:54

+1

這沒有任何意義。你無法在OCaml中動態匹配類型:語言不能像那樣工作。您可以動態匹配類型的值,這只是普通的舊模式匹配,但匹配類型不是OCaml語言允許的。你的問題仍然不是很清楚。 – 2012-03-04 22:44:08

2

當你說

match fil with 
`FilterA -> ... 

你似乎希望這將改變fil類型,但這不是它的工作原理。模式內出現filterA類型的表達式。你想要更多的東西是這樣的:

match fil with 
`FilterA { handleA = h } -> h event 

我不知道我看到有你的處理程序返回bool如果你打算使用List.iter執行它們的目的。這將返回unit,並且bool值將被丟棄。

編輯

有更深的打字問題,通過Ptival很好地解釋。所以即使你修正了你的模式,你仍然需要重新考慮你的計劃。一種可能的做法是使用變體(順便說一下不一定是多態變體)來跟蹤事件的類型。

+0

不能編譯...:'這個表達式有類型typeA,但是表達式需要類型typeB' – codablank1 2012-03-04 22:30:24

+0

我得看看你編譯的東西。你不會得到這個消息的上面的片段(我剛剛驗證)。我將把代碼擴展到一個完整的功能,也許這將澄清。 – 2012-03-04 22:35:52

+0

與上述相同,除了最後一個函數:「讓exec_filters濾波器事件= List.iter (樂趣FIL - > 匹配FIL與 |'FilterA {handleA = H} - >ħ事件;() |'FilterB {handleB = h} - > h event;() ) filters ;;' – codablank1 2012-03-04 23:44:55

4

我覺得你的代碼應該象:

let exec_filters filters event = 
    List.iter 
    (fun fil -> match fil with 
     | `FilterA fA -> fA.handleA event;() 
     | `FilterB fB -> fB.handleB event;()) 
    filters;; 

編輯:但是,這不會進行類型檢查,因爲event不能有類型typeAtypeB ...

爲什麼不把你的初始變體(typeAtypeB)多態?

你想做什麼?

+0

是的我得到的錯誤:'| 'FilterB(fB) - > fB.handleB事件; () 錯誤:這個表達式的類型爲typeA,但預期的表達式爲typeB' – codablank1 2012-03-04 22:28:37