我有枚舉類型,既可枚舉的和有界的所有值的效用函數相關聯的列表:生成整數的與Enum類型
enumerate :: (Enum a, Bounded a) => [a]
enumerate = [minBound .. maxBound]
和涉及映射枚舉類型爲整數數據類型:
data Attribute a = Attribute { test :: a -> Int
, vals :: [Int]
, name :: String }
其中vals
是表示所有可能枚舉值的整數列表。舉例來說,如果我有
data Foo = Zero | One | Two deriving (Enum,Bounded)
然後vals
將[0,1,2]
。
我希望能夠以編程方式創建這些屬性,只是給出了一個將a
映射到可枚舉類型和名稱的函數。事情是這樣的:
attribute :: (Enum b, Bounded b) => (a -> b) -> String -> Attribute a
attribute f str = Attribute (fromEnum . f) vs str
where
vs = map fromEnum enumerate
這不進行類型檢查,因爲沒有連接與類型簽名b
調用enumerate
的方式。所以我想我能做到這一點:
vs = map fromEnum $ enumerate :: [b]
但是,這並不編譯或者 - 編譯器會重命名b
到b1
。我試圖更聰明,使用GADTs擴展:
attribute :: (Enum b, Bounded b, b ~ c) => {- ... -}
vs = map fromEnum $ enumerate :: (Enum c,Bounded c) => [c]
但再次重申,c
被重命名爲c1
。
我不想包括如Attribute
型(主要是因爲我想存儲的屬性列表與b
可能不同值的參數b
類型 - 這就是爲什麼test
的類型爲a -> Int
和vals
的類型是[Int]
)。
我該如何編寫這段代碼,使其符合我的要求?
作用域類型變量工作perfecly,謝謝! – 2012-07-29 16:11:55
此外,這是我第一次見到'undefined'用於執行有用的任務。 – 2012-07-29 16:25:43
@ChrisTaylor:你當然可以使用'const'的不同特化,比如'asTypeOf2 :: [b] - >(a - > b) - > [b]',然後你可以編寫'enumerate' asTypeOf2 \'f',但這可能不值得。 – Vitus 2012-07-30 18:56:11