(Этот ответ использует данные затруднительного библиотеку, потому что я не мог получить рекурсии-схемы для компиляции.)
Мы можем моделировать диф двух деревьев, как анаморфизм или разворачивание " diff functor ", основанный на исходном функторе.
Рассмотрим следующие типы
data DiffF func r = Diff (Fix func) (Fix func)
| Nodiff (func r)
deriving (Functor)
type ExprDiff = Fix (DiffF ExprF)
Идея заключается в том, что ExprDiff
будет следовать «общей структуры» оригинальных Expr
деревьев до тех пор, пока она остается равной, но на данный момент разница встречается, мы включаем на лист Diff
, в котором хранятся два поддеревья, которые, как мы обнаружили, различны.
Фактическая функция сравнения будет:
diffExpr :: Expr -> Expr -> ExprDiff
diffExpr e1 e2 = ana comparison (e1,e2)
where
comparison :: (Expr,Expr) -> DiffF ExprF (Expr,Expr)
comparison (Fix (Const i),Fix (Const i')) | i == i' =
Nodiff (Const i')
comparison (Fix (Add a1 a2),Fix (Add a1' a2')) =
Nodiff (Add (a1,a1') (a2,a2'))
comparison (something, otherthing) =
Diff something otherthing
«Семя» из анаморфизма является парой выражений, которые мы хотим сравнить.
Если мы просто хотим предикат Expr -> Expr -> Bool
, мы сможем позже использовать катаморфизм, который обнаруживает наличие Diff
ветвей.
Откуда вы получаете исправление? – danidiaz
https: // hackage.haskell.org/package/recursion-schemes – ais
Вам, вероятно, нужен зигогистоморфный преформорфизм. Я понятия не имею, что он делает, но с таким именем я не могу представить, что многое не может * сделать. :) – chepner