transform :: Tree a -> State (Tree Int) transform Leaf = return Leaf transform (Node { left = l, right = r }) = bind ( transform l ) $ \ hl -> bind ( next ) $ \ k -> bind ( transform r ) $ \ hr -> return ( Node { left = hl, key = k, right = hr } )Wir schreiben stattdessen
transform :: Tree a -> State (Tree Int) transform Leaf = return Leaf transform (Node { left = l, right = r }) = do { hl <- transform l ; k <- next ; hr <- transform r ; return ( Node { left = hl, key = k, right = hr } ) }Aus jedem bind wird also ein Semikolon! Beachte (bestaune:) da wir die Monad-Instance selbst schreiben, indem wir die Implementierung für die Methode bind angeben, überladen wir die Semikolons. Muß man sich mal in irgendeiner anderen Sprache vorstellen!
Die Klammern und Semikolons dürfen wir sogar noch weglassen, wenn wir (wie bisher immer) alles schön untereinander schreiben.
transform (Node { left = l, right = r }) = do hl <- transform l k <- next hr <- transform r return ( Node { left = hl, key = k, right = hr } )
do { x <- f ; rest } = bind f $ \ x -> do { rest } do { let x = a; rest } = let x = a in do { rest } do { exp } = expEs gibt eine Sonderregelung: für Ausdrücke f :: m (), deren Wert also nicht interessiert, dürfen wir den Generator wie einen Ausdruck schreiben
do { () <- f ; rest } = do { f ; rest }Die Ähnlichkeit zu List comprehensions ist gewollt. Früher (vorvorige Haskell-Version) hätte man sogar schreiben dürfen
transform (Node { left = l, right = r }) = [ Node { left = hl, key = k, right = hr } | hl <- transform l , k <- next , hr <- transform r ]