1 of 28

Monader

Föreläsning 4/4 i Funktionell Programmering

2 of 28

Var är vi i programmeringsparadigmen?

  1. Funktionell Programering
  2. Syntax
  3. Internetprogrammering
  4. Paradigm

3 of 28

Var är vi i funktionell programmering?

1. Introduktion

2. Typer och Typklasser

3. Högre ordningens funktioner

4. Att använda Monader

4 of 28

Monader - agenda för idag

  1. Historisk tillbakablick
  2. do-notation
  3. Datatypskrav på Monader
  4. Maybe
  5. List
  6. IO
  7. Funktorer
  8. fmap <$>
  9. Applikativer
  10. apply <*>
  11. pure
  12. Monader
  13. bind >>=
  14. return

5 of 28

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!

6 of 28

Att använda IO-monaden som Pythonprogrammerare

  1. Skriv do först i funktionen (main till exempel)
  2. Programmera som i Python, men använd <- istället för =, putStrLn istället för print, getLine istället för input
  3. Spendera så lite tid som möjligt inuti main

7 of 28

Att använda IO-monaden som Javaprogrammerare

  • Skriv do först i funktionen
  • Skriv main inom brace:ar {} och använd semikolon (dessa kan inte väljas bort)
  • Programmera som i Java, men använd <- istället för =, putStrLn istället för System.out.println
  • Spendera så lite tid som möjligt inuti main

8 of 28

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

9 of 28

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å!

10 of 28

Maybe

Maybe är en av de enklaste monaderna. Överst i info hittar vi följande:

Några konkreta exempel:

11 of 28

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:

12 of 28

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.

13 of 28

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)

14 of 28

Lista är en funktor med map = fmap

Illustration av funktorlagarna:

Vänsterdollar <$ tillämpat på en lista ger:

Apply dollar, exempel på lista:

15 of 28

Maybe är en funktor

Illustration av fmap:

�Show me the money, Maybe:�

16 of 28

IO är en funktor

Funktorlag 1:

Funktorlag 2:

17 of 28

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:

18 of 28

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!

19 of 28

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:

20 of 28

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.

21 of 28

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

22 of 28

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.

23 of 28

Variant på Bind (>>) används för att sätta ihop beräkningar där vi ersätter det ena med det andra

24 of 28

return

Return är en funktion i Haskell som inte avslutar och inte returnerar ett värde:

25 of 28

Illustration av monadlagarna för Maybe

Här är de tre monadlagarna illustrerade med Maybe

26 of 28

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:��

27 of 28

För stora program med externa bibliotek, använd Stack

28 of 28

De tre monadlagarna för IO

  1. (return x) >>= f ==== f x�

  • m >>= return ==== m

  • (m >>= f) >>= g ==== m >>= (\x -> f x >>= g)