Ein freies Foo ist zufällig die einfachste Sache, die alle 'Foo'-Gesetze erfüllt. Das heißt, es erfüllt genau die Gesetze, die notwendig sind, um ein Foo zu sein, und nichts Besonderes.
Ein vergesslicher Funktor ist einer, der einen Teil der Struktur "vergisst", wenn er von einer Kategorie zur anderen wechselt.
Gegebene Funktoren F : D -> C, und G : C -> Dwir sagen F -| G, Fist links neben Goder Grechts neben, Fwann immer a, b: F a -> bisomorph ist a -> G b, wo die Pfeile aus den entsprechenden Kategorien stammen.
Formal bleibt ein freier Funktor neben einem vergesslichen Funktor.
Das freie Monoid
Beginnen wir mit einem einfacheren Beispiel, dem freien Monoid.
Nehmen Sie ein Monoid, das durch einen Trägersatz definiert ist T, eine binäre Funktion, um ein Elementpaar zusammenzufügen f :: T → T → T, und a unit :: T, so dass Sie ein assoziatives Gesetz und ein Identitätsgesetz haben : f(unit,x) = x = f(x,unit).
Sie können einen Funktor machen Uaus der Kategorie der Monoide (wo Pfeile Monoid Homomorphismen sind, das heißt, sie sicherstellen , dass sie Karte unitzu unitauf der anderen Monoid, und dass Sie vor oder nach der Abbildung auf die andere Monoid ohne Änderung Bedeutung komponieren kann) in die Kategorie von Sätzen (wobei Pfeile nur Funktionspfeile sind), die die Operation "vergessen" unitund Ihnen nur den Trägersatz geben.
Anschließend können Sie einen Funktor Faus der Kategorie der Sets zurück in die Kategorie der Monoide definieren, die neben diesem Funktor verbleibt. Dieser Funktor ist der Funktor, der eine Menge adem Monoid zuordnet [a], wo unit = []und mappend = (++).
Um unser bisheriges Beispiel in Pseudo-Haskell zu überprüfen:
U : Mon → Set -- is our forgetful functor
U (a,mappend,mempty) = a
F : Set → Mon -- is our free functor
F a = ([a],(++),[])
Dann, um zu zeigen, Fist kostenlos, müssen wir zeigen, dass es neben Ueinem vergesslichen Funktor bleibt, das heißt, wie wir oben erwähnt haben, müssen wir das zeigen
F a → b ist isomorph zu a → U b
Denken Sie nun daran, dass das Ziel von Fin der Kategorie Monder Monoide liegt, in der Pfeile Monoidhomomorphismen sind. Wir müssen also zeigen, dass ein Monoidhomomorphismus von [a] → bdurch eine Funktion von genau beschrieben werden kann a → b.
In Haskell nennen wir die Seite davon, in der wir leben Set(ähm, Haskdie Kategorie der Haskell-Typen, die wir vorgeben, ist Set), nur foldMapdie, wenn sie von Data.Foldableauf Listen spezialisiert ist, Typ hat Monoid m => (a → m) → [a] → m.
Daraus ergeben sich Konsequenzen als Ergänzung. Insbesondere, wenn Sie vergessen, dann bauen Sie mit kostenlos auf, dann vergessen Sie wieder, es ist genau so, wie Sie es einmal vergessen haben, und wir können dies verwenden, um den monadischen Join aufzubauen. da UFUF~ U(FUF)~ UFund wir den identitätsmonoiden Homomorphismus von [a]bis [a]durch den Isomorphismus übergeben können, der unsere Adjunktion definiert, erhalten Sie, dass ein Listenisomorphismus von [a] → [a]eine Funktion des Typs ista -> [a] , und dies ist nur eine Rückgabe für Listen.
Sie können dies alles direkter zusammenstellen, indem Sie eine Liste folgendermaßen beschreiben:
newtype List a = List (forall b. Monoid b => (a -> b) -> b)
Die freie Monade
Was ist also eine freie Monade? ?
Nun, wir machen das Gleiche wie zuvor. Wir beginnen mit einem vergesslichen Funktor U von der Kategorie der Monaden, bei der Pfeile Monadenhomomorphismen sind, zu einer Kategorie von Endofunktoren, bei denen die Pfeile natürliche Transformationen sind, und suchen nach einem Funktor, der nebeneinander bleibt dazu.
Wie hängt das mit der Vorstellung einer freien Monade zusammen, wie sie normalerweise verwendet wird?
Zu wissen, dass etwas eine freie Monade ist Free f, sagt Ihnen, dass das Geben eines Monadenhomomorphismus von Free f -> mdasselbe ist (isomorph zu) wie das Geben einer natürlichen Transformation (eines Funktorhomomorphismus) von f -> m. Denken Sie daran, F a -> bdass es isomorph zu sein muss, a -> U bdamit F neben U bleibt. Hier werden Monaden auf Funktoren abgebildet.
F ist mindestens isomorph zu dem FreeTyp, den ich in meinem freePaket für Hackage verwende.
Wir könnten es auch in engerer Analogie zum obigen Code für die freie Liste konstruieren, indem wir es definieren
class Algebra f x where
phi :: f x -> x
newtype Free f a = Free (forall x. Algebra f x => (a -> x) -> x)
Kaffeefreie Comonaden
Wir können etwas Ähnliches konstruieren, indem wir den richtigen Zusatz zu einem vergesslichen Funktor betrachten, vorausgesetzt, er existiert. Ein Cofree-Funktor ist einfach / richtig neben einem vergesslichen Funktor, und aus Symmetriegründen ist das Wissen, dass etwas eine Cofree-Comonade ist, dasselbe wie das Wissen, dass das Geben eines Comonad-Homomorphismus aus w -> Cofree fdasselbe ist wie das Geben einer natürlichen Transformation von w -> f.