A Monad egy speciális adattípus a funkcionális programozási nyelvekben , amelyhez be lehet állítani egy kötelező sorrendet bizonyos műveletek végrehajtásához a tárolt értékeken [1] . A monádok lehetővé teszik a műveletek sorrendjének beállítását, mellékhatásokkal járó műveletek és egyéb olyan műveletek végrehajtását, amelyeket a funkcionális programozási paradigmában más módon nehéz vagy lehetetlen megvalósítani.
A monád fogalom és kifejezés eredetileg a kategóriaelméletből származik , ahol kiegészítő szerkezetű funktorként határozzák meg. Az 1980-as évek végén és az 1990-es évek elején kezdődő kutatások megállapították, hogy a monádok látszólag eltérő számítástechnikai problémákat egyetlen funkcionális modellbe hozhatnak. A kategóriaelmélet számos formai követelményt is támaszt.[ mi? ] , az úgynevezett monádi törvények , amelyeket minden monádnak be kell tartania, és amelyek segítségével ellenőrizhető a monádi kód.
A monádokat leggyakrabban funkcionális programozási nyelvekben használják . Lusta értékelési modell esetén a redukció sorrendje ismeretlen. Például a számítás 1 + 3 + 6lecsökkenthető 1 + 9vagy -ra 4 + 6. A monádok lehetővé teszik a csökkentés elrendelését. Ezért van egy ironikus állítás, hogy a monádok a pontosvessző operátor túlterhelésének egyik módja.
A monád egy olyan tároló, amely tetszőleges típusú értéket tárol. Egy bind függvénynek kell lennie, amely két argumentumot vesz fel: a monád aktuális értékét, és egy olyan függvényt, amely az aktuális monád által tartalmazott típusú értéket veszi fel, és visszaadja az új monádot. A bind függvény meghívásának eredménye egy új monád lesz, amelyet úgy kapunk, hogy az első argumentumot alkalmazzuk a másodikra. Így nézhet ki egy monád a Java imperatív nyelvben és annak egyik megvalósítása, a Maybe konténer:
import java.util.function.Function ; interfész Monad < T > { < U > Monad < U > bind ( Funkció < T , Monad < U >> f ); } class Talán < T > megvalósítja a Monad < T > { privát döntő Tval ; _ public Talán ( T val ) { ez . val = val ; } public T getVal () { return val ; } @Override public < U > Monad < U > bind ( Function < T , Monad < U >> f ) { if ( val == null ) return new Talán < U > ( null ); visszatér f . alkalmazni ( val ); } } public class MonadApp { public static void main ( String [] args ) { Talán < Integer > x = new Talán <> ( 5 ); Monád < Egész > y = x . bind ( v -> new Talán <> ( v + 1 )) . bind ( v -> new Talán <> ( v * 2 )); Rendszer . ki . println ( (( Talán < Integer > ) y ). getVal () ); } }A Java 8-ban bemutatott funkcionális interfészek lehetővé teszik a monádszerű interfész megvalósítását.
A Monad osztály jelen van a standard modulban Prelude. Ennek az osztálynak a megvalósítása bármilyen egyparaméteres típust igényel (genus type * -> *). A monádnak négy módszere van
osztály Funktor f ahol fmap :: ( a -> b ) -> f a -> f b osztály Funktor f => Applikatív f ahol tiszta :: a -> f a ( <*> ) :: f ( a -> b ) -> f a -> f b ( *> ) :: f a -> f b -> f b ( <* ) :: f a -> f b -> f a -- m :: * -> * osztály Applikatív m => Monád m ahol ( >>= ) :: m a -> ( a -> m b ) -> m b ( >> ) :: m a -> m b -> m b -- alapértelmezés szerint megvalósítva: a >> b = a >>= \_ -> b return :: a -> m a -- = tiszta hiba :: String -> m a -- by-calls errorWithoutStackTrace alapértelmezés szerintA módszer returnzavaró lehet az imperatív nyelvekben jártas programozók számára: nem szakítja meg a számítást, csak a típus tetszőleges értékét csomagolja abe egy monádba m. A módszernek failsemmi köze a monádok elméleti természetéhez, de egy monádi kiértékelésen belüli mintaillesztési hiba esetén alkalmazzák. [2] ). Az operátor >>=egy kötelező függvény. Az operátor >> az operátor speciális esete >>=, akkor használjuk, ha a kötés eredménye nem fontos számunkra.
Néhány típus, amely megvalósítja a Monad osztályt:
A nyelvnek van do-notation is, ami kényelmesebb módja a monadikus függvények írásának. Ebben a példában a -notationt f1használja , de bind operátorokkal írják: dof2
f1 = do s <- getLine putStrLn $ "Szia" ++ s putStrLn "Viszlát" f2 = getLine >>= ( \ s -> putStrLn $ "Hello " ++ s ) >> putStrLn "Viszlát"