можно обобщить:
сейчас у меня есть код, который по сути работает так:
data Expression
= Literal Bool
| Variable String
| Not Expression
| Or Expression Expression
| And Expression Expression
deriving Eq
simplify :: Expression -> Expression
simplify (Literal b) = Literal b
simplify (Variable s) = Variable s
simplify (Not e) = case simplify e of
(Literal b) -> Literal (not b)
e' -> Not e'
simplify (And a b) = case (simplify a, simplify b) of
(Literal False, _) -> Literal False
(_, Literal False) -> Literal False
(a', b') -> And a' b'
simplify (Or a b) = case (simplify a, simplify b) of
(Literal True, _) -> Literal True
(_, Literal True) -> Literal True
(a', b') -> Or a' b'
И еще много таких шаблонов, касающихся всех способов, которыми можно упростить логическое выражение. Однако, по мере того, как я добавляю больше операторов и правил, это становится невероятно большим и неуклюжим. Тем более что некоторые правила необходимо добавить дважды, чтобы учесть коммутативность.
Как я могу красиво рефакторировать множество и множество паттернов, некоторые из которых (большинство, я бы сказал) даже симметричны (например, паттерны And и Or)?
Прямо сейчас добавление правила для упрощенияAnd (Variable "x") (Not (Variable "x"))
вLiteral False
требует, чтобы я добавил два вложенных правила, что почти оптимально.