Arrows
Ein Vortrag von
Mario Rauschenberg, Bjarne Großmann
Agenda
Einleitung
Funktionen, Monaden und Arrows
Funktionen, Monaden und Arrows
Arrows im Detail
Beispiel
15.01.2009
Bjarne Großmann, Mario Rauschenberg
2
Einleitung
Was sind eigentlich „Arrows“?
Lediglich eine Verallgemeinerung der Monaden!
???
15.01.2009
Bjarne Großmann, Mario Rauschenberg
3
Einleitung
Quizfrage: Was ist eine Monade?
a) Abstrakter Datentyp
b) Beschreibung einer einheitlichen Schnittstelle
c) Containerklasse für unterschiedliche Typen
d) Verpackte Berechnungen mit Seiteneffekten
)
g ,
g
e) Strategie, um Berechnungen zu kombinieren
f) Ich hab keine Ahnung
15.01.2009
Bjarne Großmann, Mario Rauschenberg
4
Back to the Roots
Back to
Funktionen und ihre Komposition
f
g
h
fgh
fgh
:: a ‐> b
>b
:: b ‐> c
:: c ‐> d
:: a > d
:: a ‐> d
= h . g . f
a b
f
15.01.2009
b c
g
c d
h
Bjarne Großmann, Mario Rauschenberg
5
Back to the Roots
Back to
Komplexere Funktionen
f1,g1,h1
f1
1 h1
f2,g2,h2
f3,g3,h3
f4 g4 h4
f4,g4,h4
:: a ‐> Maybe
>M b b
:: a ‐> (b, s)
:: a ‐> [b]
:: a > (s > (a s))
:: a ‐> (s ‐> (a, s))
fgh = fn . gn . hn ???
a Maybe b
f
15.01.2009
b Maybe c
g
Bjarne Großmann, Mario Rauschenberg
6
Beispiel: Maybe
Beispiel: Maybe
f
g
h
fgh
:: a ::
a ‐>> Maybe b
Maybe b
:: b ‐> Maybe c
:: c ‐> Maybe d
:: a ‐>> Maybe d
:: a Maybe d
a b
fgh
1. Lösungsversuch
fgh
g x = case f x of
Nothing ‐> Nothing
Just y ‐> case g y of
Nothing ‐> Nothing
Just z ‐> h z
15.01.2009
Bjarne Großmann, Mario Rauschenberg
7
Beispiel: Maybe
Beispiel: Maybe
f
g
h
f h
fgh
:: a ‐> Maybe b
:: b ‐> Maybe c
:: c ‐> Maybe d
:: a ‐> Maybe d
b d
(a > Maybe b) (Maybe
(a ‐> Maybe
b)
(Maybe a ‐> Maybe
a > Maybe b)
helper
f f*
2. Lösungsversuch
helper
helper f Nothing
helper f (Just x)
:: (a ::
(a ‐>> Maybe b) Maybe b) ‐>> (Maybe a (Maybe a ‐>> Maybe b)
Maybe b)
= Nothing
= f x
fgh = (helper h) . (helper g) . f
15.01.2009
Bjarne Großmann, Mario Rauschenberg
8
Beispiel: Tupel
Beispiel: Tupel
f
g
h
fgh
:: a ‐> (b, String)
:: b ‐> (c, String)
:: c ‐> (d, String)
:: a ‐> (d, String)
helper
:: (a ‐> (b, String)) ‐> ((a, String) ‐> (b, String))
helper g (fx, fs) = let (gx, gs) = g fx
in (gx, fs++gs)
fgh = (helper h) . (helper g) . f
(
) (
)
15.01.2009
Bjarne Großmann, Mario Rauschenberg
9
Beispiel: Liste
Beispiel: Liste
f
g
h
fgh
:: a ‐> [b]
:: b ‐> [c]
:: c ‐> [d]
:: a ‐> [d]
helper helper f x :: (a ‐> [b]) ‐> ([a] ‐> [b])
= concat (map f x)
fgh = (helper h) . (helper g) . f
15.01.2009
Bjarne Großmann, Mario Rauschenberg
10
Beispiel: Status
Beispiel: Status
f
g
h
fgh
:: a ‐> (s ‐> (b, s))
:: b ‐> (s ‐> (c, s)) :: c ‐> (s ‐> (d, s)) :: a ‐> (s ‐> (d, s)) helper helper g x s :: (a ‐> (s ‐> (b, s))) ‐> ((s ‐> (a, s)) ‐> (s ‐> (b, s)))
= let (x1, s1) = x s
in g x1 s1
fgh = (helper h) . (helper g) . f
(
) (
)
15.01.2009
Bjarne Großmann, Mario Rauschenberg
11
Beispiel: Zusammenfassung
Beispiel: Zusammenfassung
f1
helper1
f2
helper2
f3
helper3
f4
helper :: a ‐> Maybe b
:: (a ‐> Maybe b) ‐> (Maybe a ‐> Maybe b)
:: a ‐> (b, s)
:: (a ‐> (b, s)) ‐> ((a, s) ‐> (b, s))
:: a ‐> [b] :: (a ‐> [b]) ‐> ([a] ‐> [b]) :: a ‐> (s ‐> (d, s)) :: (a ‐> (s ‐> (b, s))) ‐> ((s ‐> (a, s)) ‐> (s ‐> (b, s)))
fgh = (helper hn) . (helper gn) . fn
(
) (
)
15.01.2009
Bjarne Großmann, Mario Rauschenberg
12
Monaden
newtype MyMonad t = M Maybe t
newtype MyMonad t = M (t, String)
newtype MyMonad t = M [t]
newtype MyMonad t = M (s ‐> (t, s))
15.01.2009
f
helper
:: a ‐> M b
:: (a ‐> M b) ‐> (M a ‐> M b)
:: (a ‐> M b) ‐> M a ‐> M b
(a > M b) > M a > M b
:: M a ‐> (a ‐> Mb) ‐> M b
(>>=)
= helper
= helper
fgh x
return
= f x >>= g >>= h
?=? x >>= f >>= g >>= h
?=? x >>= f >>= g >>= h
:: a ‐> M a
fgh x
= return x return x >>= f f >>= g g >>= h
h
Bjarne Großmann, Mario Rauschenberg
13
Monaden
In Haskell:
class Monad m where
return :: a ‐> m a
(>>=) :: m a ‐> (a ‐> m b) ‐> m b
Maybe a
a ‐> b
[a]
s ‐> (a, s)
Either e
Monade
15.01.2009
Bjarne Großmann, Mario Rauschenberg
14
Funktionskomposition
Funktionen kombinieren
f :: a ‐> b
g :: b ‐> c
Bisher
fgfg :: a ‐> c
= f . g
Funktionen als Parameter
:: (a ‐> b) ‐> (b ‐> c) ‐> (a ‐> c)
comb
comb h k
= k . h
(.) für einfache Funktionen
15.01.2009
Bjarne Großmann, Mario Rauschenberg
15
Funktionskomposition
Funktionen kombinieren
f :: a ‐> m b
g :: b ‐> m c
Bisher
fg :: a ‐> m c
fg x = (f x) >>= g
Funktionen als Parameter
comb
comb h k x
:: (a ‐> m b) ‐> (b ‐> m c) ‐> (a ‐> m c)
= (h x) >>= k
(>>=) für monadische Funktionen?
((>>=) :: m a ‐> (a ‐> m b) ‐> m b
)
(
)
15.01.2009
Bjarne Großmann, Mario Rauschenberg
16
Funktionskomposition
Abstraktion des Operators
comb newtype Kleisli m a b
mab
(>‐>) K f (>‐>) K g
:: (a ‐> m b) ‐> (b ‐> m c) ‐> (a ‐> m c)
= K { runK
K { runK :: a ‐> m b }
a >mb}
:: Kleisli m a b ‐> Kleisli m b c ‐> Kleisli m a c
= K (\x ‐> f x >>= g)
Der erste Arrow: Kleisli Arrow!
g
Anwendung ähnlich wie bei Monaden
f
:: K m a b
g
:: K m b c
fg x = runK (f >‐> g) x
15.01.2009
Bjarne Großmann, Mario Rauschenberg
17
Arrows
Weitere Abstraktion
Kleisli Arrow nicht nur für Monaden:
f newtype Arrow b c
(>>>)
(>>>) arr
:: b ‐> c
= A ( runA :: b ‐> c)
:: A b c ‐>> A c d :: A b c A c d ‐>> A b d
Abd
:: (b ‐> c) ‐> A b c
Arrows für beliebige Funktionen
f
:: A a b
g
:: A b c
fg x x = runA
runA (f
(f >>> g) x
>>> g) x
15.01.2009
Bjarne Großmann, Mario Rauschenberg
18
Was sind Arrows?
Was sind Arrows?
Erklärung von Wikibooks
Kombination von Funktions
Kombination von Funktions‐Objekten
Objekten (Roboter) mit verschiedenen In‐ und Outputs (Fließbänder)
15.01.2009
Bjarne Großmann, Mario Rauschenberg
19
arr
Verknüpfung mit In‐ und Output
arr :: Arrow a => (b ‐> c) ‐> a b c
15.01.2009
Bjarne Großmann, Mario Rauschenberg
20
(>>>)
Output von f als Input von g
(>>>) :: Arrow a => a b c ‐> a c d ‐> a b d
15.01.2009
Bjarne Großmann, Mario Rauschenberg
21
returnA
Arrow – Identität
returnA :: Arrow a => a b b
Arrow a > a b b
returnA = arr id
15.01.2009
Bjarne Großmann, Mario Rauschenberg
22
Unterschied zu Monaden
Unterschied zu Monaden
Arrows sind eine Erweiterung von Monaden
Monaden sind eine Erweiterung von sind eine Erweiterung von
Funktionen
Also: Arrows
Al A
abstrahieren Funktionen
b
hi
F ki
Arrows haben expliziten Input
p
p
Funktion
Monade
Arrow
f
m
a
15.01.2009
Bjarne Großmann, Mario Rauschenberg
23
Monaden durch Arrows
Monaden durch Arrows
newtype
yp Kleisli m a b = K (a ‐> m b)
(
)
instance Monad m => Arrow (Kleisli m) where
arr f = K (\b ‐> return f b)
K f >>> K g
= K (\b ‐> f b >>= g)
15.01.2009
Bjarne Großmann, Mario Rauschenberg
24
„The real flexibility with arrows comes with the „The
real flexibility with arrows comes with the
ones that aren't monads, otherwise it's just a clunkier syntax
syntax”
‐ Philippa Cowderoy
15.01.2009
Bjarne Großmann, Mario Rauschenberg
25
first & second
& second
Mehrere Inputs von denen einer verarbeitet wird.
first :: Arrow a => a b c ‐> a (b, d) (c, d)
second :: Arrow a => a b c ‐> a (d, b) (d, c)
Arrow a > a b c > a (d b) (d c)
15.01.2009
Bjarne Großmann, Mario Rauschenberg
26
( )
(***)
Zwei Inputs durch jeweils anderes
j
Funktionsobjekt bearbeitet
(***) Arrow a > a b c > a d e > a (b d) (c e)
(***) :: Arrow a => a b c ‐> a d e ‐> a (b,d) (c,e)
15.01.2009
Bjarne Großmann, Mario Rauschenberg
27
(&&&)
Ein Input wird in beide Funktionen „geklont“.
(&&&) Arrow a > a b c > a b d > a b (c d)
(&&&) :: Arrow a => a b c ‐> a b d ‐> a b (c,d)
15.01.2009
Bjarne Großmann, Mario Rauschenberg
28
Wozu das ganze?
Wozu das ganze?
Generalisierung von Monaden bzw. g
Funktionen und „Funktionsartigen“
Größere Flexibilität als bei Monaden
„Stream‐Prinzip“
S
Pi i “
15.01.2009
Bjarne Großmann, Mario Rauschenberg
29
Funktionen als Arrows
Funktionen als Arrows
instance Arrow (‐>) where
arr f = f
f f
first f = f *** id
second f = id *** f
((***)) f g f g ~(x
(x,y) = (f x, g y)
y) = (f x g y)
15.01.2009
Bjarne Großmann, Mario Rauschenberg
30
Parser Beispiel
Parser‐Beispiel
Monadischer HTML‐Parser
Input: <xhtml>
Input: <xhtml>
<html>
<body>
<?php>
Ineffizient!
15.01.2009
fail!
Bjarne Großmann, Mario Rauschenberg
31
Parser Beispiel
Parser‐Beispiel
Erweiterung von Swierstra und Duponcheel: Vorausschauendes Parsen
Input: <xhtml>
<html>
<body>
<? h >
<?php>
fail!
15.01.2009
Bjarne Großmann, Mario Rauschenberg
32
Parser Beispiel
Parser‐Beispiel
Monadischer Parser
newtype
yp Parser s a = P ([s] ‐> Maybe
([ ]
y ((a,[s]))
,[ ]))
symbol :: s ‐> Parsers s s
symbol s = P (\xs ‐> case xs of
[ ] ‐> nothing
(x : xs‘) ‐> if x == s
then just (s, xs‘)
else nothing )
15.01.2009
Bjarne Großmann, Mario Rauschenberg
33
Parser Beispiel
Parser‐Beispiel
Monadische Parser kombinieren
instance MonadPlus Parsers where
P a (+++) P b = P (\s ‐> case a s of
Just (x, s‘) ‐> Just (x, s‘)
Nothing ‐> b s )
Problem: „Space Leak
Problem: Space Leak“
15.01.2009
Bjarne Großmann, Mario Rauschenberg
34
Parser Beispiel
Parser‐Beispiel
Erweiterung
data Parser s a b = P (StaticParser
(
s) (DynamicParser
)( y
s a b))
data StaticParser s = SP Bool [s]
newtype DynamicParser s a b = DP ( (a, [s]) ‐> (b, [s]) )
spChar :: Char ‐> StaticParser Char
spChar c = SP False [c]
dpChar :: Char ‐> DynamicParser Char Char Char
d Ch
dpChar c = DP (\
(\ ( _ , x:xs) ‐> (c, xs) )
(
) (
))
simple :: Char ‐> Parser Char Char Char
simple c = P (spChar
i l
P ( Ch c ) (dpChar
) (d Ch c))
15.01.2009
Bjarne Großmann, Mario Rauschenberg
35
Parser Beispiel
Parser‐Beispiel
Instance MonadPlus Parsers where
P (SP empty1 start1) DP (dp1) (+++) P (SP empty2 start2) DP (dp2) = P ( SP (empty1 || empty2) (start1++start2) DP (\xss ‐> case xss of
[ ] = if empty1 then dp1 [] else dp2 []
j@(x:xs) = if x `in` start1 then dp1 j else
if x `in` start2 then dp2 j else
if empty1 then dp1 j else dp2 j
)
)
15.01.2009
Bjarne Großmann, Mario Rauschenberg
36
Parser Beispiel
Parser‐Beispiel
Bind‐Operator
(>>=) :: Parsers s a ‐> ( a ‐> Parsers s b) ‐> Parsers s b
… ist nicht möglich, da der statische Teil von a „vergessen“ wird.
“ id
15.01.2009
Bjarne Großmann, Mario Rauschenberg
37
Parser Beispiel
Parser‐Beispiel
Arrow‐Parser
Instance Arrow (Parser s) where
(
)
arr :: Arrow a => (b ‐> s) ‐> a b s
arr f = P (SP True [ ]) (DP (\ (b,s) ‐> (f b, s) ) )
P (SP empty1 start1) DP (dp1) >>> P (SP empty2 start2) DP (dp2) = P ( SP (empty1 && empty2) (start1 `union` if empty1 then start2 else [ ]) DP (dp1 . dp2)
)
15.01.2009
Bjarne Großmann, Mario Rauschenberg
38
Anwendungsbeispiele von Arrows
Anwendungsbeispiele von Arrows
Parser (z.B. auch HXT)
Automaten
Stream‐Computing
15.01.2009
Bjarne Großmann, Mario Rauschenberg
39
Fazit
Mächtiges Konzept für funktionsartige g g
Vorgänge
Allgemeinerer Entwurf als Monaden
Weg von Pure‐Functions
W
P
F
i
Verständnis ist „nicht einfach“
„
15.01.2009
Bjarne Großmann, Mario Rauschenberg
40
Quellen (einige)
Quellen (einige)
http://www.haskell.org/haskellwiki
h
//
h k ll
/h k ll iki
http://www.wikibooks.org
John Hughes: Generalising Monads to Arrows:
http //www cs chalmers se/~rjmh/Papers/arrows pdf
http://www.cs.chalmers.se/~rjmh/Papers/arrows.pdf
John Hughes: Programming with Arrows:
http://www.cs.chalmers.se/~rjmh/afp‐arrows.pdf
Hudak Courtney Nilsson Peterson: Arrows Robots and Reactive Functional Programming
Hudak, Courtney, Nilsson, Peterson: Arrows, Robots
http://www.haskell.org/yale/papers/oxford02/.oxford02.pdf
Albert Lai: HXT Arrow Lessons:
http://www.vex.net/~trebla/haskell/hxt‐arrow/index.xhtml
p //
/
/
/
/
15.01.2009
Bjarne Großmann, Mario Rauschenberg
41