Monáda (funkcionální programování)
Author
Albert FloresMonáda je funktoriální datový typ vybavený dvěma přirozenými transformacemi umožňujícími asociativní skládání operací nad monádami. Formálně je monáda monoidem v kategorii endofunktorů v kategorii typů (v Haskellu kategorie Hask). Obecně je-li (\mathcal{C},\otimes,I) tenzorová kategorie (kde \otimes je bifunktor a I \in \mathrm{Ob}(\mathcal{C})), monády jsou monoidy v ([\mathcal{C},\mathcal{C}],\circ,I).
Přirozené transformace jsou u každé monády T multiplikace \mu:T^2 \rightarrow T a jednotka \eta:I \rightarrow T splňující \mu \circ \mu T = \mu \circ T\mu (T^3 \rightarrow T) a \mu \circ \eta T = 1 = \mu \circ T\eta. Ve funkcionálním programování se tyto operace zpravidla nazývají join a unit. +more Příkladem monády je kontinuace, kde \eta je funkcí z A do (A \rightarrow R) \rightarrow R definovaná jako \eta x=\lambda f. f(x) a speciální operace vázání je m >\. \. \. >\. \. = f = \lambda g. m(\lambda x. f(x)(g)), přičemž \mu x je x >\. \. \. >\. \. = \lambda y. y.
Monády umožňují formulovat kód s vedlejšími efekty tak, aby byl referenčně transparentní, a tedy „čistý“ (ve funkcionálním smyslu). Monády jsou zpravidla generické a jejich druh je (* \rightarrow *) \rightarrow *.
Z každého endofunktoru lze vytvořit volnou monádu.
Příklad
Kontinuace v C++ lze reprezentovat (s využitím statického polymorfismu) následující třídou:
template class Cont { std::function&)> fn; public: Cont(const decltype(fn)& f) : fn(f) {} Cont(T&& x) : fn([x](auto f) { return f(x); }) {} std::any operator(const std::function& f) const { return fn(f); } };
Aby byla Cont funktorem, musíme implementovat fmap nebo bind:
template class M, typename T, typename U> struct Bind; template struct Bind { std::function f; auto operator(const Cont& m) { return [this,m](auto g) { return m([this,g](auto x) { return f(x)(g); }); }; } };
C++ nemá typy vyšších druhů, nicméně pomocí specializace šablon můžeme dosáhnout stejného efektu. Konkrétně můžeme například definovat generické monadické operace fmap a join.
template class M, typename T, typename U> struct Fmap { std::function f; auto operator(const M&) const; };
template class M, typename T> struct Join { auto operator(const M>&) const; };
template class M, typename T, typename U> auto Fmap::operator(const M& m) const { std::cerr {[&](auto x) { return M{f(x)}; }}(m); }
template class M, typename T> auto Join::operator(const M>& m) const { std::cerr ,T>{[](M x) { return x; }}(m); }
Takto koncipovaný kód má tu výhodu, že poskytuje definice monadických funkcí bez ohledu na konkrétní typ. Proto stačí pro konkrétní monadický typ implementovat pouze buď bind, nebo fmap a join, podobně jako v čistě funkcionálních jazycích à la Haskell.
Externí odkazy
[url=https://web.archive.org/web/20171015150120/https://scitech.blog/article?id=14e7d734f959f9b3-9bb465d0-8f580c8c-085d8148-f645e774]A monad is...[/url]
Kategorie:Funkcionální programování Kategorie:Teorie kategorií