2012-01-22 94 views
3

類似領域在this答案,「附加」元信息類型的建議方式是使用記錄:記錄在OCaml的

type _foo = ... 
and foo = {n:_foo; m:meta} 

但如果我有多種類型,我想用包元信息?顯然記錄類型中的所有字段名稱必須具有不同的名稱,並寫入:

type _foo = ... 
and foo = {n:_foo; m:meta} 
... 
type _fooX = ... 
and fooX = {nX:_fooX; mX:meta} 

似乎是多餘的:/。類是解決這個問題的唯一方法?如果可能的話,我想避免處理類。

回答

5

您可以使用參數化類型。

type 'a wrapped = { base: 'a; extra: meta } 
+0

如果我的類型是遞歸的? – pbp

+0

沒有一個你可能想要的具體例子很難說。上面的'wrapped'類型將包裝任何類型,無論是否遞歸。如果你想在類型''a'和'meta'類型之間遞歸,你可能需要另一個類型參數。也許你會希望'meta'本身是一個參數化類型?儘量保持簡單! –

+0

例如:'type exp = BinOp exp * op * exp | int'的const,我希望子表達式也可以用'meta'包裝。 – pbp

2

傑弗裏的解決方案是正確的,並且對遞歸類型完美縮放。

type location 
type 'a loc = { a : 'a; loc : location } 

type exp = Int of int | Add of exp loc * exp loc 

它仍然有可能使用你的類型的前兩個時間的定義, 如下:

type exp_data = Int of int | Add of exp * exp 
and exp = exp_data loc 

最後,一個略微不同的風格是用「開放遞歸」,即用自由參數而不是遞歸出現僅定義「去反映類型」open_exp。然後您可以通過獲取定點來獲取遞歸類型;您可以採取不同的固定點,一個沒有附加信息,另一個固定點例如交錯。這是一個在遞歸網站插入信息的通用結構,其術語級別的對象允許在遞歸函數中編寫不同的東西(記憶,分析,調試等)。

type 'e open_exp = Int | Add of 'e * 'e 
type simple_exp = Simple of simple_exp open_exp 
type located_exp = Loc of located_exp loc open_exp