Подтвердить что ты не робот

Переопределение (==) в Haskell

У меня есть следующие типы алгебраических данных:

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)

Это выражения в простом языке игрушек.

Однако, поскольку я получаю Eq, Op Plus (Var "a") (Var "b) не считается равным Op Plus (Var "b") (Var "a"), хотя я бы хотел рассматривать a+b как равное выражение для b+a.

Как мне изменить (==) только для этих экземпляров, не указывая поведение (==) для всех остальных экземпляров?

4b9b3361

Ответ 1

Вы можете добиться этого, сделав 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

Это сравнило бы Op Plus так, как хотелось бы, но по-прежнему не хватает других случаев для Op.

Edit:

Самый простой способ реализовать специальные случаи для (==) на 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]

Ответ 2

Если вы хотите настраивать поведение для 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

Позвольте вам определить все выражения структурно равными, за исключением приложений функций к аргументам, которые являются равными только по имени (что может быть или не быть полезным).