Решил написать кое-что для манипулирования формулами нулевого и первого порядка. Притом, чтобы не дублировать код, сделал так:
data ShallowFormula0 a uo bo f = Atom a
| Un uo f
| Bin bo f f
deriving (Eq, Ord)
data ShallowFormula1 a uo bo q f = F0 (ShallowFormula0 a uo bo f)
| Q q f
deriving (Eq, Ord)
type Formula0 = Fix (ShallowFormula0 Prop UnOp BinOp)
type Formula1 = Fix (ShallowFormula1 (Pred Term) UnOp BinOp Quantifier)
и сделал их также инстансами класса
class Formula f a uo bo | f -> a, f -> uo, f -> bo where
-- smart constructors
atom :: a -> f
unary :: uo -> f -> f
binary :: bo -> f -> f -> f
quantif :: Quantifier -> f -> Formula1
-- преобразования туда-сюда без потерь и с потерями
firstOrder :: f -> Formula1
truncate :: f -> Formula0
-- и, из-за использования индексов де Брёйна в Formula1,
isValid :: f -> Bool
позволяющего конструировать их единообразно. А что делать с деконструкцией? Включить в класс набор функций
asAtom :: f -> Maybe a,
asQuantif :: f -> (q, f) etc.? Чего-то резко забыл, как принято деконструировать ADT’ы.
Заодно принимаю предложения по переименованию (
Formula1 как-то не с тем ассоциируется) и переделке этих типов — сейчас в коде инстанса
Formula Formula1 (Pred Term) UnOp BinOp в двух методах двухуровневый матчинг, в одном из уровней по конструкторам
ShallowFormula0, что явно не дело (может, есть смысл сделать по типу на конструктор, а потом собрать их в оба нужных типа как-то иначе, перераспределив код (отфакторизовав какие-нибудь классы и инстансы, возможно) к этим мелким типам, а не двум конечным? Я явно что-то упускаю.
Возможно, и ну его, и работать только с формулами первого порядка, т. к. формулы нулевого полностью вкладываются (пропозициональные переменные = нульместные предикатные символы), но ещё подумываю, начав с одного представления правил вывода
data InfRule f = InfRule {
arity :: Int,
tryApply :: [f] -> Maybe f,
isApplied :: [f] -> f -> Bool
}
-- пример:
ruleHypothesis :: Formula f a uo bo => f -> InfRule f
ruleHypothesis fh = InfRule {
arity = 0,
tryApply = tryApply',
isApplied = isApplied'
} where
tryApply' [] = Just fh
tryApply' _ = Nothing
isApplied' [] fh -> True
isApplied' _ _ -> False
перейти потом к более правильному на основе схем формул. Их тип получился бы аналогично
ShallowFormula1 «добавлением конструктора». Так что в любом случае issue имеется.