Functioneel Programmeren Daan Leijen
Wat gaan we doen? 3 fundamentele principes van computatie Equationeel redeneren IO-monad GUI's in Haskell (wxHaskell) Bouncing balls
De 3 principes van computatie Geformuleerd door de wiskundige Leibniz in 1666 in zijn "Dissertatio de arte combinatoria" Leibniz probeerde alle redenaties te reduceren tot een combinatie van basis waarden zoals getallen, letters, geluiden en kleuren. Abstractie Parametrisatie Reductie
0. Waarden 32 2*16 twee-en-dertig 4*4 + 4*4 thirty-two …
0. Vele soorten waarden 32(getal) 'a'(letter) "hoi"(string) ["hoi","hi"](lijst van strings) length(functies) (plaatjes (bitmaps)) { } (set van kleuren)
0. Waarden Programmeren is niets anders dan een waarde opschrijven…
1. Abstractie 4*4 + 4*4 let x = 4*4 in x+x of ook: x + x where x = 4*4
2. Reductie We hebben een reductie regel nodig om te "rekenen" Formeel: let x = e 1 in e 2 == e 2 [x e 1 ] Heet ook: β-reductie of Leibniz-rule
2. Reductie Reductie in de praktijk: let x = 4*4 in x+x == { reductie (abstractie) } 4*4 + 4*4 == { wiskunde } 32
3. Parametrisatie Definieer 1 functie voor vele waarden: fun :: Int -> Int fun a = let x = a*a in x+x
3. Parametrisatie Ook hier geldt reductie fun 4 =={ parametrisatie } let x = 4*4 in x+x =={ abstractie } 4*4 + 4*4 =={ wiskunde } 32
Helium Reductie is wel veel werk, dus dat laten we de computer doen…
Equationeel redeneren Som van een lijst: sum :: [Int] Int sum [] = 0 sum (x:xs) = x + sum xs
Equationeel redeneren sum [1,2] =={ syntax } sum (1 : (2 : [])) =={ leibniz } 1 + sum (2:[]) =={ leibniz } 1 + (2 + sum []) == { leibniz } =={ wiskunde } 3
Functies Met de basis principes kun je alleen functies construeren: Voor gegeven parameters altijd hetzelfde resultaat.
Vergelijk let x = "hi" in (x ++ x) let x = getLine in (x ++ x) String x = System.In.GetLine(); System.Out.WriteLine(x); (getLine ++ getLine)
Side-effects Het gaat mis omdat "getLine" geen functie is. We krijgen steeds andere resultaten. Er bestaan vele van dit soort operaties: "putStr", "random", "showWindow", etc.
"do" notatie Met de "do" notatie kunnen we expliciet zijn hoe vaak iets geevalueerd word. do x <- getLine putStr (x ++ x) do x <- getLine y <- getLine putStr (x ++ y)
Typering We willen ons eerdere voorbeeld voorkomen. getLine :: IO String putStr :: String -> IO () getLine ++ getLine
"do" notatie De "do" notatie pakt IO waardes uit. do x <- getLine putStr (x ++ x) :: IO String :: String :: IO ()
Pure waarden Met "return" maken we van een gewone waarde een IO computatie: return :: a -> IO a do x <- getLine return x == getLine
Sequence Abstraheren over computaties: sequence :: [IO a] -> IO [a] sequence [] = return [] sequence (io:ios) = do x <- io xs <- sequence ios return (x:xs)
Voorbeeld Laat een lijst van strings zien of putStrs :: [String] -> IO [()] putStrs xs = sequence (map putStr xs) putStrs = sequence. map putStr
Sequence_ Vergeet het resultaat: sequence_ :: [IO a] -> IO () sequence_ ios = do xs <- sequence ios return ()
Ultimate IO: GUI's
The perfect GUI library Efficient Portable Native look-and-feel Lots of standard functionality Easy to use
wxWidgets Large C++ library for writing GUI's: Portable (Windows, GTK, MacOS X, Symbian, etc) Wrapper around native controls. Free and open source Active developer/user community Dynamic event model
AOL communicator
Audacity
wxHaskell A binding of Haskell and wxWidgets It is huge: 2800 methods 1400 constants 500 classes
Demo
The technology behind the winners..
It is portable
Minimal program main = start gui gui :: IO () gui = do frame [text := "hello!"] return () [Prop (Frame ())] -> IO (Frame ())
Buttons main = start gui gui :: IO () gui = do f <- frame [text := "Hello!"] q <- button f [text := "Quit"] set f [layout := widget q] Frame a ->[Prop (Button ())]->IO (Button ())
Event handlers gui :: IO () gui = do f <- frame [text := "Hello!"] b <- button f [text := "Quit",on command := close f] set f [layout := widget b]
Setters set w ps = sequence (map (set1 w) ps) set1 w p = …
Layout combinators layout := widget b margin 10 $ floatCenter (widget b) margin 10 $ column 5 [floatCenter(caption "Hello"),floatCenter(widget b)] Layout -> Layout
Complex layout
Bouncing Balls
Representation Iedere bal is gerepresenteerd als een lijst van al zijn toekomstige posities. t0 = [] … t10 = [[(4,8),(4,7),(4,6),…],[(9,1),(9,0),(9,1),(9,2),…]] … t11 = [[(4,7),(4,6),…],[(9,0),(9,1),(9,2),…]]
Questions?