Monad este un tip de date special în limbaje funcționale de programare , pentru care este posibilă setarea unei secvențe imperative pentru efectuarea anumitor operații asupra valorilor stocate [1] . Monadele vă permit să setați secvența operațiilor, să efectuați operații cu efecte secundare și alte acțiuni care sunt dificil sau imposibil de implementat în paradigma de programare funcțională în alte moduri.
Conceptul și termenul monadului provin inițial din teoria categoriilor , unde este definit ca un functor cu structură suplimentară. Cercetările începute la sfârșitul anilor 1980 și începutul anilor 1990 au stabilit că monadele ar putea aduce probleme aparent disparate de informatică într-un singur model funcțional. Teoria categoriilor propune, de asemenea, câteva cerințe formale.[ ce? ] , așa-numitele legi monadice , care trebuie respectate de orice monadă și pot fi folosite pentru verificarea codului monadic.
Monadele sunt utilizate cel mai frecvent în limbaje de programare funcționale . Cu un model de evaluare leneș, ordinea reducerii este necunoscută. De exemplu, calculul 1 + 3 + 6poate fi redus la 1 + 9sau 4 + 6. Monadele permit comandarea reducerii. Prin urmare, există o afirmație ironică că monadele sunt o modalitate de a supraîncărca operatorul punct și virgulă.
O monada este un container care stochează o valoare de tip arbitrar. Trebuie să aibă o funcție de legătură care ia două argumente: valoarea curentă a monadei și o funcție care ia o valoare de tipul pe care o conține monada curentă și returnează noua monada. Rezultatul apelării funcției bind va fi o nouă monada obținută prin aplicarea primului argument celui de-al doilea. Așa ar putea arăta o monada în limbajul imperativ Java și una dintre implementările sale, containerul Maybe:
import java.util.function.Function ; interfață Monad < T > { < U > Monad < U > bind ( Funcție < T , Monad < U >> f ); } clasa Poate < T > implementează Monad < T > { Tval final privat ; _ public Poate ( T val ) { asta . val = val ; } public T getVal () { return val ; } @Override public < U > Monad < U > bind ( Function < T , Monad < U >> f ) { if ( val == null ) return new Maybe < U > ( null ); întoarce f . aplica ( val ); } } public class MonadApp { public static void main ( String [] args ) { Maybe < Integer > x = new Maybe <> ( 5 ); Monada < Integer > y = x . bind ( v -> nou Poate <> ( v + 1 )) . bind ( v -> nou Poate <> ( v * 2 )); Sistem . afară . println ( (( Poate < Integer > ) y ). getVal () ); } }Interfețele funcționale introduse în Java 8 vă permit să implementați o interfață asemănătoare monadelor.
Clasa Monad este prezentă în modulul standard Prelude. Implementarea acestei clase necesită orice tip cu un parametru (tip de gen * -> *). Monada are patru metode
clasă Functor f unde fmap :: ( a -> b ) -> f a -> f b clasă Functor f => Aplicativ f unde pur :: a -> f a ( <*> ) :: f ( a -> b ) -> f a -> f b ( *> ) :: f a -> f b -> f b ( <* ) :: f a -> f b -> f a -- m :: * -> * class Aplicative m => Monad m unde ( >>= ) :: m a -> ( a -> m b ) -> m b ( >> ) :: m a -> m b -> m b -- implementat implicit: a >> b = a >>= \_ -> b return :: a -> m a -- = pur fail :: String -> m a -- by- calls errorWithoutStackTrace în mod implicitMetoda returnpoate fi confuză pentru programatorii familiarizați cu limbaje imperative: nu întrerupe calculul, ci doar împachetează o valoare arbitrară de tip aîntr-o monada m. Metoda failnu are nimic de-a face cu natura teoretică a monadelor, dar este folosită în cazul unei erori de potrivire a modelului în cadrul unei evaluări monadice. [2] ). Operatorul >>=este o funcție de legare. Operatorul >> este un caz special al operatorului >>=, folosit atunci când rezultatul legării nu este important pentru noi.
Câteva tipuri care implementează clasa Monad:
Limbajul are și donotația -, care este o modalitate mai convenabilă de a scrie funcții monadice. În acest exemplu , f1folosește do-notația, dar este f2scris folosind operatori de legare:
f1 = do s <- getLine putStrLn $ "Bună ziua " ++ s putStrLn "La revedere" f2 = getLine >>= ( \ s -> putStrLn $ "Bună ziua " ++ s ) >> putStrLn "La revedere"