Monader
Föreläsning 4/4 i Funktionell Programmering
Var är vi i programmeringsparadigmen?
Var är vi i funktionell programmering?
1. Introduktion
2. Typer och Typklasser
3. Högre ordningens funktioner
4. Att använda Monader
Monader - agenda för idag
Historisk tillbakablick
Saunders Mac Lane och Samuel Eilenberg 1940-talet : Kategoriteori
“En monad är en monoid i kategorin för endofunktorer, vad är problemet?”/citat ur slack-chatten
1980-talet: Haskell föddes utan monader
1989: Moggi - vi borde använda monader i Haskell!
1990-talet: Philip Wadler. Såhär borde vi göra
00-talet: Applikativa funktorer tillkom!
Att använda IO-monaden som Pythonprogrammerare
Att använda IO-monaden som Javaprogrammerare
Minnesregler / Dad jokes
FAMous for a FABULous PR-trick.�Funktor (som är) Applikativ (kan bli en) Monad�fmap <$> är ungefär apply <*> som är ungefär bind som är ungefär liftA2/liftM2 (u:et är ungefär)�pure är ungefär return
Alla monader arbetar med typer inom kontexten för en annan typ
Exempel på typer som inte är monadiska: Int, Bool, Char, Double.
Alla dessa typer kan dock verka inom kontexten för andra typer som är monadiska.
Men String då?
Eftersom en sträng i Haskell är en lista av Chars och alla listor är monader så är strängar monader också!
Maybe
Maybe är en av de enklaste monaderna. Överst i info hittar vi följande:
Några konkreta exempel:
Listor är monader
Kontexten för en lista är att värdet/funktionen ligger i en lista.
Så här är typen för lista definierad:
IO är en monad
IO har den enklaste typen av alla Monader. Den ser ut såhär:
Med hjälp av denna kan vi skapa IO String, IO Int, IO Integer och liknande.
En stor skillnad på dessa typer och andra är att det inte går att fly denna typ.
head tar ut det första värdet ur en lista. Detta värde är sedan utanför sin monad.�fromJust tar ut värdet från en maybe (fungerar bara på värden som börjar med Just)�Det går inte att fly från en IO-monad. När ett värde väl har hamnat här så kommer det aldrig ut.
Funktorer
För att få kalla dig för en funktor så behöver du implementera fmap.
fmap är en generalisering av den högre ordningens funktionen som heter map
f i början betyder funktor.
En operator för funktorer är vänsterdollar: <$ som ersätter värdet i funktorn med det som står till vänster. En annan operator är dollar <$> som gör samma sak som `fmap`
fmap behöver uppfylla två funktorlagar:�1. fmap id == id�2. fmap (g.f) == (fmap g).(fmap f)
Lista är en funktor med map = fmap
Illustration av funktorlagarna:
Vänsterdollar <$ tillämpat på en lista ger:
Apply dollar, exempel på lista:
�
Maybe är en funktor
Illustration av fmap:
�Show me the money, Maybe:�
IO är en funktor
Funktorlag 1:
Funktorlag 2:
Hur blir <$ och <$> för IO?
Som de tidigare! Sätt in värdet till vänster i kontexten för värdet till höger.
…och <$> fungerar på samma sätt som map, här med en lambda:
Applikativ Funktor
Mycket modernt programmeringskoncept från 2008. Det presenterades i papperet “Applicative programming with effects” av Conor McBride och Ross Paterson.
För att få kallas applikativ funktor så behöver du (1) antingen implementera <*> som utläses apply eller funktionen liftA2. Dessa påminner om varandra och om du implementerar en så kommer den att användas som den andra. �Operatorn påminner om fmap med skillnaden att operatorn måste existera i samma kontext som den applikativa funktorn/monaden.
En annan operation som du behöver (2) är pure som sätter in ett värde inuti kontexten för en applikativ funktor… konkreta exempel kommer!
Introduktion till <*> (som utläses ap) och pure
Den första skillnaden mellan <*> och <$> map är att <*> ställer kravet på att funktionen som ska verka på värdet inom kontexten behöver själv ligga inom kontexten. Konkreta exempel:
Introduktion till liftA2
liftA2 är en mycket viktig funktion inom den applikativa monaden. Den lyfter in en funktion utanför kontexten och tillämpar den på två värden inom kontexten.
�
Monader
En monad är en applikativ funktor som implementerar bind (>>=) och return.
Källa: https://wiki.haskell.org/All_About_Monads#The_monad_laws
https://wiki.haskell.org/All_About_Monads#T
�
Bind (>>=)
Typsignatur
‘
Bind kan skapa en kedja av operationer på ett värde som slutar i ett resultat. Detta är grunden till exempelvis Streams i Java och naturligtvis varför vi gör Monader i Haskell.
Variant på Bind (>>) används för att sätta ihop beräkningar där vi ersätter det ena med det andra
return
Return är en funktion i Haskell som inte avslutar och inte returnerar ett värde:
Illustration av monadlagarna för Maybe
Här är de tre monadlagarna illustrerade med Maybe
De tre monadlagarna med listan
Första lagen:�(return x) >>= f ==== f x�Vi kan sätta in någonting i en lista�m >>= return ==== m�Att göra return på en lista ger oss listan�Tredje lagen, illustration:��
För stora program med externa bibliotek, använd Stack
De tre monadlagarna för IO