我有枚举类型,既可枚举的和有界的所有值的效用函数相关联的列表:生成整数的与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