Bezpłatne foo okazuje się najprostszą rzeczą, która spełnia wszystkie prawa „foo”. To znaczy, że spełnia dokładnie prawa niezbędne do bycia foo i nic więcej.
Zapominający funktor to taki, który „zapomina” część struktury, przechodząc z jednej kategorii do drugiej.
Biorąc pod uwagę funktory F : D -> C, i G : C -> D, jak mówimy F -| G, Fjest on przyległy do G, lub Gjest przyległy do, Filekroć forall a, b: F a -> bjest izomorficzny a -> G b, gdzie strzałki pochodzą z odpowiednich kategorii.
Formalnie wolny funktor pozostaje przyległy do zapomnianego funktora.
Wolny Monoid
Zacznijmy od prostszego przykładu, wolnej monoidy.
Weź monoid, który jest zdefiniowany przez jakiś zestaw nośnej T, funkcja binarna mash parę elementów ze sobą f :: T → T → T, a także unit :: Ttakie, które mają prawo zrzeszania się, prawo oraz tożsamości: f(unit,x) = x = f(x,unit).
Możesz zrobić funktor Uz kategorii monoidów (gdzie strzałki są homomorfizmami monoidów, tzn. Zapewniają, że odwzorowują unitsię unitna innym monoidie, i że możesz komponować przed lub po mapowaniu na drugą monoidę bez zmiany znaczenia) do kategorii zestawów (gdzie strzałki są tylko strzałkami funkcyjnymi), które „zapominają” o operacji uniti po prostu dają ci zestaw nośny.
Następnie możesz zdefiniować funktor Fz kategorii zestawów z powrotem do kategorii monoidów, która pozostaje przyległa do tego funktora. Ten funktor jest funktorem, który odwzorowuje zbiór ana monoid [a], gdzie unit = []i mappend = (++).
Aby przejrzeć nasz dotychczasowy przykład w pseudo-Haskell:
U : Mon → Set -- is our forgetful functor
U (a,mappend,mempty) = a
F : Set → Mon -- is our free functor
F a = ([a],(++),[])
Następnie pokazanie Fjest bezpłatne, musimy wykazać, że jest on sąsiadujący z Uzapomnianym funktorem, to znaczy, jak wspomniano powyżej, musimy pokazać, że
F a → b jest izomorficzny a → U b
pamiętajcie teraz, że cel Fjest w kategorii Monmonoidów, gdzie strzały są homomorfizmami monoidów, więc musimy pokazać, że homomorfizm monoidów z [a] → bmożna dokładnie opisać funkcją a → b.
W Haskell nazywamy stronę tego, w której żyjemy Set(er, Haskkategoria typów Haskell, którą udajemy, jest ustawiona), właśnie foldMap, która, gdy specjalizujemy Data.Foldablesię w Listach, ma typ Monoid m => (a → m) → [a] → m.
Istnieją konsekwencje wynikające z tego, że jest to dodatek. Zwłaszcza, że jeśli zapomnisz, a następnie zbuduj za darmo, to zapomnij jeszcze raz, tak jak raz zapomniałeś, a my możemy to wykorzystać do zbudowania połączenia monadycznego. ponieważ UFUF~ U(FUF)~ UF, i możemy przekazać tożsamość monomorfizmu monoidu od [a]do [a]poprzez izomorfizm, który określa nasze przyleganie, uzyskajmy, że izomorfizm listy od [a] → [a]jest funkcją typu a -> [a], a to jest po prostu powrót do list.
Możesz to wszystko skomponować bardziej bezpośrednio, opisując listę w tych kategoriach za pomocą:
newtype List a = List (forall b. Monoid b => (a -> b) -> b)
Wolna monada
Czym jest wolna monada ?
Cóż, robimy to samo, co poprzednio, zaczynamy od zapomnianego funktora U z kategorii monad, w których strzały są homomorfizmami monad, do kategorii endofunkcji, w których strzały są naturalnymi transformacjami, i szukamy funktora, który jest pozostawiony obok siebie do tego.
Jak to się ma do pojęcia wolnej monady, jak się zwykle używa?
Wiedząc, że coś jest wolną monadą, Free fmówi ci, że nadanie monomorfizmowi monady z Free f -> m, jest tym samym (izomorficznym), co nadanie naturalnej transformacji (homomorfizm funktorski) f -> m. Pamiętaj, że F a -> bmusi być izomorficzny, aby a -> U bF pozostawał przyległy do U. U tutaj mapowane monady na funktory.
F jest co najmniej izomorficzny do Freetypu używanego w moim freepakiecie podczas włamań.
Możemy również skonstruować go w ścisłej analogii do powyższego kodu dla wolnej listy, definiując
class Algebra f x where
phi :: f x -> x
newtype Free f a = Free (forall x. Algebra f x => (a -> x) -> x)
Cofree Comonady
Możemy skonstruować coś podobnego, patrząc na właściwe połączenie z zapomnianym funktorem, zakładając, że istnieje. Funktor Cofree jest po prostu / właściwie przylegający / do zapomnianego funktora, a symetria, wiedząc, że coś jest cofree comonad, jest tym samym, co wiedza, że nadanie homomorfizmu comonad z w -> Cofree fjest tym samym, co danie naturalnej transformacji w -> f.