Monad är en speciell datatyp i funktionella programmeringsspråk , för vilka det är möjligt att ställa in en imperativ sekvens för att utföra vissa operationer på lagrade värden [1] . Monads låter dig ställa in sekvensen av operationer, utföra operationer med biverkningar och andra åtgärder som är svåra eller omöjliga att implementera i det funktionella programmeringsparadigmet på andra sätt.
Monadbegreppet och termen kommer ursprungligen från kategoriteori , där den definieras som en funktor med ytterligare struktur. Forskning som började i slutet av 1980-talet och början av 1990-talet fastställde att monader kunde föra till synes olika datavetenskapliga problem till en enda funktionell modell. Kategoriteori ställer också flera formkrav.[ vad? ] , de så kallade monadiska lagarna , som måste följas av vilken monad som helst och kan användas för att verifiera den monadiska koden.
Monader används oftast i funktionella programmeringsspråk . Med en lat utvärderingsmodell är minskningsordningen okänd. Till exempel kan beräkningen 1 + 3 + 6reduceras till 1 + 9eller 4 + 6. Monader tillåter beställning av minskningen. Därför finns det ett ironiskt påstående att monader är ett sätt att överbelasta semikolonoperatorn.
En monad är en behållare som lagrar ett värde av en godtycklig typ. Den måste ha en bindningsfunktion som tar två argument: monadens nuvarande värde och en funktion som tar ett värde av den typ som den aktuella monaden innehåller och returnerar den nya monaden. Resultatet av att anropa bindfunktionen blir en ny monad som erhålls genom att applicera det första argumentet på det andra. Så här kan en monad i Java imperativspråket och en av dess implementeringar, Maybe-behållaren, se ut:
importera java.util.function.Function ; gränssnitt Monad < T > { < U > Monad < U > bind ( Funktion < T , Monad < U >> f ); } klass Kanske implementerar < T > Monad < T > { privat final Tval ; _ public Kanske ( T val ) { detta . val = val ; } public T getVal () { return val ; } @Override public < U > Monad < U > bind ( Funktion < T , Monad < U >> f ) { if ( val == null ) returnera ny Kanske < U > ( null ); återvända f . tillämpa ( val ); } } public class MonadApp { public static void main ( String [] args ) { Kanske < Integer > x = new Maybe <> ( 5 ); Monad < Heltal > y = x . binda ( v -> ny Kanske <> ( v + 1 )) . binda ( v -> new Maybe <> ( v * 2 )); System . ut . println ( (( Kanske < Heltal > ) y ). getVal () ); } }Funktionella gränssnitt introducerade i Java 8 låter dig implementera ett monadliknande gränssnitt.
Monad-klassen finns i standardmodulen Prelude. Implementeringen av denna klass kräver vilken typ av enparameter som helst (genustyp * -> *). Monaden har fyra metoder
klass Funktion f där fmap :: ( a -> b ) -> f a -> f b klass Funktion f => Applikativ f där ren :: a -> f a ( <*> ) :: f ( a -> b ) -> f a -> f b ( *> ) :: f a -> f b -> f b ( <* ) :: f a -> f b -> f a -- m :: * -> * klass Applikativ m => Monad m där ( >>= ) :: m a -> ( a -> m b ) -> m b ( >> ) :: m a -> m b -> m b -- implementerat som standard: a >> b = a >>= \_ -> b return :: a -> m a -- = rent misslyckande :: String -> m a -- by- calls errorWithoutStackTrace som standardMetoden returnkan vara förvirrande för programmerare som är bekanta med imperativa språk: den avbryter inte beräkningen, utan packar bara in ett godtyckligt värde av typen ai en monad m. Metoden failhar inget att göra med monadernas teoretiska natur, utan används vid ett mönstermatchningsfel inom en monadisk utvärdering. [2] ). Operatören >>=är en bindande funktion. Operatören >> är ett specialfall av operatören >>=, som används när resultatet av bindningen inte är viktigt för oss.
Några typer som implementerar Monad-klassen:
Språket har också do-notation, vilket är ett bekvämare sätt att skriva monadiska funktioner. I det här exemplet f1använder den do-notation, men f2skrivs med bindoperatorer:
f1 = gör s <- getLine putStrLn $ "Hej " ++ s putStrLn "Adjö" f2 = getLine >>= ( \ s -> putStrLn $ "Hej " ++ s ) >> putStrLn "Adjö"