oad*_*ams 13 haskell types typeclass algebraic-data-types
我有以下代数数据类型:
data Exp
= Con Int
| Var String
| Op Opkind Exp Exp
| Input
deriving (Show,Eq)
data Opkind
= Plus | Minus | Mult | Div | More | Equal
deriving (Show,Eq)
Run Code Online (Sandbox Code Playgroud)
这表示用简单的玩具语言表达.
但是,因为我得出了Eq,即使我想把它视为一个平等的表达式,Op Plus (Var "a") (Var "b)
也不算等于.Op Plus (Var "b") (Var "a")
a+b
b+a
如何更改(==)
这些实例,而不必指定(==)
所有其他实例的行为?
Jak*_*nge 18
你可以通过使Exp成为Eq的实例而不是派生Eq来实现这一点:
instance Eq Exp where
(Con a) == (Con b) = a == b
(Var a) == (Var b) = a == b
(Op Plus a b) == (Op Plus c d) = (a == c && b == d) || (a == d && c == b)
Input == Input = True
_ == _ = False
Run Code Online (Sandbox Code Playgroud)
这将以所需的方式比较Op Plus,但仍然缺少Op的其他案例.
编辑:
在Op上实现(==)特殊情况而不会丢失Exp上的派生的最简单方法,我想到的就是这样:
data Exp
= Con Int
| Var String
| EOp Op
| Input
deriving (Show, Eq)
data Op = Op Opkind Exp Exp deriving (Show)
instance Eq Op where
(Op Plus e1 e2) == (Op Plus e3 e4) = (e1 == e3 && e2 == e4) || ( e1 == e4 && e2 == e3)
(Op kind1 e1 e2) == (Op kind2 e3 e4) = and [kind1 == kind2, e1 == e3, e2 == e4]
Run Code Online (Sandbox Code Playgroud)
如果您想要自定义行为Op
,但是您的数据类型的所有其他变体的常规行为,您需要突破Op
自己的类型.
例如:
data Exp
= Con Int
| Var String
| Input
| PrimOp Op
deriving (Show,Eq)
data Op = Op Opkind Exp Exp
deriving Show
data Opkind
= Plus | Minus | Mult | Div | More | Equal
deriving (Show,Eq)
-- equality on (symbolic) functions, perhaps?
instance Eq Op where
(Op a _ _) == (Op b _ _) = a == b
Run Code Online (Sandbox Code Playgroud)
让我们定义所有结构上相等的表达式,除了函数到参数的应用程序,它们只是名称相同(可能有用也可能没用).