cha*_*ni2 1 compiler-construction haskell derived-instances
我需要为数据派生Eq,但对于某些构造函数,我想忽略一些字段.数据用于表示DataTypes(我们正在开发编译器):
data DataType
= Int | Float | Bool | Char | Range | Type
| String Width
| Record (Lexeme Identifier) (Seq Field) Width
| Union (Lexeme Identifier) (Seq Field) Width
| Array (Lexeme DataType) (Lexeme Expression) Width
| UserDef (Lexeme Identifier)
| Void | TypeError
deriving (Ord)
Run Code Online (Sandbox Code Playgroud)
我需要忽略它出现的每个contstructor中的Width 字段.
如果要使用自定义Eq语义,则无法派生Eq.您必须手动编写实例.
一个常见的诀窍是:
a == b = toDataType' a == toDataType' b这至少使它不那么特别,在它自己的类型中捕获不同的Eq语义,它可以/可以/派生.
Don的另一种方法是使用包装器类型来编码特殊字段所需的实例:
newtype Metadata a = Metadata { unMetadata :: a }
instance Eq (Metadata a) where
(==) _ _ = True
instance Ord (Metadata a) where
compare _ _ = EQ
Run Code Online (Sandbox Code Playgroud)
然后,您可以Width将DataType定义中的所有内容替换为Metadata Width并派生实例.
data DataType
= Int | Float | Bool | Char | Range | Type
| String (Metadata Width)
| Record (Lexeme Identifier) (Seq Field) (Metadata Width)
| Union (Lexeme Identifier) (Seq Field) (Metadata Width)
| Array (Lexeme DataType) (Lexeme Expression) (Metadata Width)
| UserDef (Lexeme Identifier)
| Void | TypeError
deriving (Eq, Ord)
Run Code Online (Sandbox Code Playgroud)
此解决方案使您的DataType定义更加冗长(并且更明确?),但在使用这些Width值时需要包装和解包.