我想要一种数据类型来表示可以通过特定名称寻址的有限整数集.我认为最好的方法是使用Enum.
但是,有一个小问题.我知道定义Enum的唯一方法是这样的:
data MyDataType = Foo | Bar | Baz
instance Enum MyDataType
toEnum 0 = Foo
toEnum 1 = Bar
toEnum 2 = Baz
fromEnum Foo = 0
fromEnum Bar = 1
fromEnum Baz = 2
Run Code Online (Sandbox Code Playgroud)
请注意,我必须重复两次相同的对 - 一次定义整数到枚举映射,另一次定义枚举到整数映射.
有没有办法避免这种重复?
Rob*_*een 52
data MyDataType = Foo | Bar | Baz deriving (Enum)
Run Code Online (Sandbox Code Playgroud)
aug*_*tss 32
instance Enum MyDataType where
fromEnum = fromJust . flip lookup table
toEnum = fromJust . flip lookup (map swap table)
table = [(Foo, 0), (Bar, 1), (Baz, 2)]
Run Code Online (Sandbox Code Playgroud)
Gre*_*ber 13
接受的解决方案的问题是编译器不会告诉您何时丢失表中的枚举.该deriving Enum解决方案是伟大的,但如果你想拥有数字任意映射将无法正常工作.另一个答案表明泛型或模板Haskell.这通过使用来跟进Data.
{-# Language DeriveDataTypeable #-}
import Data.Data
data MyDataType = Foo | Bar | Baz deriving (Eq, Show, Data, Typeable)
toNumber enum = case enum of
Foo -> 1
Bar -> 2
Baz -> 4
Run Code Online (Sandbox Code Playgroud)
toNumber添加新构造函数时,我们将在案例映射中获得编译器警告.
现在我们只需要能够将代码转换为数据,以便映射可以自动反转.这里我们生成table在接受的解决方案中提到的相同内容
table = map (\cData -> let c = (fromConstr cData :: MyDataType) in (c, toNumber c) )
$ dataTypeConstrs $ dataTypeOf Foo
Run Code Online (Sandbox Code Playgroud)
您可以填写Enum与已接受答案中相同的课程.没有提到你也可以填写Bounded课程.
| 归档时间: |
|
| 查看次数: |
20773 次 |
| 最近记录: |