Hoezo wordt de code niet mooier op? Of je nou dit typt:
Python:
1
2
3
4
5
| def example():
print "What's your name?"
x = raw_input()
print "Hello " + x
return |
Of 1 van de volgende alternatieven:
Haskell:
1
2
3
4
5
6
| example :: IO ()
example
= do _ <- putStrLn "What's your name?"
x <- getLine
_ <- putStrLn ("Hello " ++ x)
return () |
Haskell:
1
2
3
4
5
6
| -- We hoeven geen naam te geven aan het resultaat van putStrLn:
example'
= do putStrLn "What's your name?"
x <- getLine
putStrLn ("Hello " ++ x)
return () |
Haskell:
1
2
3
4
5
6
| -- En aangezien het resultaat van putStrLn altijd () is,
-- kunnen we `return ()` weglaten:
example''
= do putStrLn "What's your name?"
x <- getLine
putStrLn ("Hello " ++ x) |
NB 1: x in de Haskell code is de naam van het resultaat van getLine, niet een mutable memory location zoals in Python.
NB 2: return () in Haskell doet niets met de control flow zoals in Python, maar maakt hier een IO actie aan met als resultaat (). Het resultaat van een do-block is altijd het resultaat van de laatste actie.
Ik snap wel hoe ze werken en waarom ze bestaan, maar misschien moet ik het gewoon vaker gebruiken en ga ik het dan waarderen...
Monads bestaan iig omdat wiskundige bestaat en je ziet ze overal wel terug.
Voorbeeld van een monad: de verzameling.
[list=1]
• Gegeven een willekeurige a, kan ik de verzameling {a} maken;
• Gegeven een verzameling van a'tjes en gegeven een functie die a'tjes afbeeldt op b'tjes, kan ik een verzameling b'tjes maken;
• Gegeven een verzameling van verzameling van a'tjes, kan ik een verzameling van a'tjes maken.
Oftewel, de typeconstructor Set met de volgende drie functies vormt een monad:
**
code:
1
2
3
| unit :: a -> Set a
map :: (a -> b) -> Set a -> Set b
join :: Set (Set a) -> Set a |
(** Er zijn ook een paar regels waar deze drie functies aan moeten voldoen, maar die laat ik voorlopig buiten beschouwing)
Tegenwoordig kun je trouwens ook al in .NET monad comprehension queries schrijven. Stel dat de hypothetische class IO bestond, dan zou je het volgende kunnen schrijven:
C#:
1
2
3
4
5
| var example = from _ in IO.Print("What's your name?")
from x in IO.GetLine
from _ in IO.Print("Hello " + x)
select 0;
int x = example.run(); |