Können wir für eine beliebige Datenstruktur mit einem Fixpunkt eine Monoidalgebra konstruieren, ohne alle Fälle manuell zu spezifizieren?Monoidale Falten an Fixpunkten
Angenommen, wir erhalten den Datentyp Expr
wie folgt. Mit der Bibliothek können wir einen Basisfunktor ExprF
ableiten, der automatisch auch Functor
, und Traversable
Instanzen hat. Jetzt
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TemplateHaskell #-}
import Data.Semigroup (Sum(..))
import Data.Functor.Foldable
import Data.Functor.Foldable.TH
import Prelude hiding (fail)
data Expr = Var String
| Const Int
| Add [Expr]
| Mult [Expr]
deriving Show
$(makeBaseFunctor ''Expr)
expr :: Fix ExprF
expr = ana project $ Add [Const 1, Const 2, Mult [Const 3, Const 4], Var "hello"]
, lassen Sie uns sagen, dass wir die Anzahl der Blätter in expr
zählen möchten. Wir können leicht eine Algebra für eine so kleine Datenstruktur schreiben:
alg (ConstF _) = 1
alg (VarF _) = 1
alg (AddF xs) = sum xs
alg (MulF xs) = sum xs
Nun wir cata alg expr
nennen können, die 5
, das richtige Ergebnis zurückgibt.
Nehmen wir an, Expr
wird wirklich groß und komplex und wir wollen nicht Fälle für alle Datenkonstruktoren manuell schreiben. Wie kann cata
die Ergebnisse aus allen Fällen kombinieren? Ich vermute, dass dies möglich ist mit Monoid
s, möglicherweise in Verbindung mit dem Const
Funktor (nicht ganz sicher über diesen letzten Teil).
fail = getSum $ foldMap (const (Sum 1) . unfix) $ unfix expr
fail
kehrt 4
, während wir 5
Blätter tatsächlich haben. Ich gehe davon aus, dass das Problem im Fixpunkt liegt, da wir nur eine Schicht von Fix
schälen können und somit die Mult [..]
nur als ein Blatt gezählt wird.
Ist es möglich, generisch den gesamten Fixpunkt zu falten und die Ergebnisse in einer Monoid
-ähnlichen Struktur ohne manuell alle Instanzen zu sammeln? Was ich will ist eine Art von foldMap
aber in einer allgemeineren Art und Weise.
Ich habe das Gefühl, ich vermisse etwas wirklich offensichtlich.
'fail' zählt die Kinder des obersten Knotens von' expr'. Im Allgemeinen kommt es nicht in die Nähe der Blätter. Es ist nicht das 'alg' eines geeigneten' cata'. – pigworker
@pigworker Ich hatte den gleichen Verdacht. Jetzt suche ich nur noch nach einem akkumulierenden Katamorphismus, den ich nicht für 60 Fälle schreiben muss (einen pro Konstruktor), sondern eher monoidale Eigenschaften für rekursive Fälle. Ich denke, das sollte möglich sein, aber ich habe keine Ahnung, wie ich dieses Problem angehen soll. – ThreeFx
Was ein Blatt kennzeichnet, ist, dass die Summe der Blattzählungen seiner Kinder Null ist, weil es keine Kinder gibt. Kann man nun anhand der Summe der Blattzählungen der Kinder die Blattanzahl der Eltern berechnen? – pigworker