假设我们有以下数据类型:
data Cmd = Cmd0 Opcode | Cmd1 Opcode Arg | Cmd2 OPcode Arg Arg
data Opcode = NOP | INC | ADD | MUL deriving (Enum)
data Arg = W32 Int | W16 Int | W8 Int
我们的想法是拥有一个产生顺序操作码编号的操作码类型。有没有办法为Cmd值指定约束,比如说:Cmd0只有NOP操作码,Cmd1只有INC, Cmd2仅是ADD或MUL值。我试图使用GATD,但它们按类型而不是值进行操作。
或者反之亦然有没有办法为Cmd的每个值生成一个后续的操作码 手动或不使用TH为每个值声明fromEnum方法?
答案 0 :(得分:8)
您可以使用单独的OpCode
类型:
data Opcode0 = NOP
data Opcode1 = INC
data Opcode2 = ADD | MUL
data Cmd = Cmd0 Opcode0 | Cmd1 Opcode1 Arg | Cmd2 Opcode2 Arg Arg
现在有时您可能希望将所有操作码视为单一类型,比如将它们放在列表中。为此,您可以使用Opcode类型的类型类并使用existential types:
class OpcodeCl a where --empty classes seem to be allowed (in GHC at least)
instance OpcodeCl Opcode0 where
instance OpcodeCl Opcode1 where
instance OpcodeCl Opcode2 where
data Opcode = forall a . (OpcodeCl a) => Op { unOp :: a }
我怀疑你不能在Opcode
执行任何操作,因为类OpcodeCl
没有方法。您可以向OpcodeCl
添加有用的方法,例如转换为Int
或从{{1}}转换。