From 76b9e428426e2afeb67f48c094bbc0225563dd3d Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Tue, 24 Nov 2015 14:29:20 +0100 Subject: FFP - 06 (partially) & 06b --- ws2015/ffp/blaetter/06/FFP_U06_Monaden.hs | 193 ++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 ws2015/ffp/blaetter/06/FFP_U06_Monaden.hs (limited to 'ws2015/ffp/blaetter/06/FFP_U06_Monaden.hs') diff --git a/ws2015/ffp/blaetter/06/FFP_U06_Monaden.hs b/ws2015/ffp/blaetter/06/FFP_U06_Monaden.hs new file mode 100644 index 0000000..f444ad0 --- /dev/null +++ b/ws2015/ffp/blaetter/06/FFP_U06_Monaden.hs @@ -0,0 +1,193 @@ +-- Fortgeschrittene Funktionale Programmierung, +-- LMU, TCS, Wintersemester 2015/16 +-- Steffen Jost, Alexander Isenko +-- +-- Übungsblatt 06a. 25.11.2015 +-- +-- Thema: Monaden-Gesetze, Erste Schritte mit Monaden und Do-Notation +-- +-- Hier machen wir ein paar erste Schritte mit Monaden. +-- Wer das alles schon kennt und bereits von woanders her +-- mit der Do-Notation vertraut ist, sollte stattessen +-- die B-Version dieses Übungsblattes machen: +-- einen applikativen Parser bauen. +-- +-- Gehen Sie diese Datei durch und bearbeiten Sie +-- alle Vorkommen von undefined bzw. die mit -- !!! TODO !!! +-- markierten Stellen. Testen Sie Ihre Lösungen mit GHCi! + + +---- A6-1 Monaden Gesetze nachweisen +-- +-- +-- a) +-- Auf Folie 04-42 fehlt der Beweis für die Assoziativität +-- Maybe-Instanz für die Typklasse Monad. +-- Führen Sie den Beweis aus! +-- (Geht ganz analog zu den anderen beiden Beweisen, d.h. +-- Definitionen ausfalten und umformen. +-- Bei Abgabe: Bitte zusätzlich kurze Begründung für jeden Schritt angeben!) +{- +Zu Zeigen: + Ausdruck + m >>= (\x-> ((f x) >>= g)) + ist gleich zu + (m >>= f) >>= g +-} + +-- !!! TODO !!! + + +-- b) +{- Beweisen Sie, dass folgende Definition + + instance Monad [] where + return x = [x] -- (Mo1) + xs >>= f = concat (map f xs) -- (Mo2) + + das Monaden-Gesetz "Links-Identität" einhält! + + Folgende Definition sind dabei eventuell nützlich: + + concat :: [[a]] -> [a] + concat [] = [] -- (CcN) + concat (xs:xss) = xs ++ concat xss -- (CcC) + + (++) :: [a] -> [a] -> [a] + (++) xs [] = xs -- (ANr) + (++) [] ys = ys -- (ANl) + (++) (x:xs) ys = x : (xs ++ ys) -- (ACl) + + map :: (a -> b) -> [a] -> [b] + map _ [] = -- (MpN) + map f (x:xs) = (f x) : (map f xs) -- (MpC) +-} + +-- !!! TODO !!! + + + + +---- A6-2 Either-Monade und Do-Notation +-- +-- In der vorletzten Vorlesung am 12.11. haben wir gesehen +-- wie der Datentyp Either der Standardbibliothek zum +-- Funktor gemacht werden kann. +-- +-- Machen Sie diesen Datentyp nun zu einer Monade! +-- Um Namenskonflikten aus dem Weg zu gehen, +-- definieren wir Either einfach noch mal neu: + +data Entweder a b = Eines a | Anderes b + deriving (Show, Eq) + +-- Die Idee ist dabei die gleiche wie bei Maybe, +-- nur das "Nothing" hier noch einen Wert tragen kann. + +instance Functor (Entweder a) where + fmap f (Anderes x) = Anderes $ f x + fmap _ (Eines x) = Eines x -- Because x@(Either a b) is not (Either a c), even if we can prove that x is Left. + +instance Applicative (Entweder a) where + pure = Anderes + (Anderes f) <*> (Anderes x) = Anderes $ f x + (Eines x) <*> _ = Eines x -- ditto + _ <*> (Eines x) = Eines x + +instance Monad (Entweder a) where + (Anderes a) >>= f = f a + (Eines x) >>= _ = Eines x -- ditto + +-- Applicative Tests: +-- (*) <$> (Anderes 3) <*> (Anderes 4) +-- (*) <$> (Eines 3) <*> (Anderes 4) +-- (*) <$> (Anderes 3) <*> (Eines 4) + + +-- b) +-- Verallgemeinern Sie folgende gewöhnlichen Funktionsdefinition, +-- welche Kenntnis des Typs Entweder voraussetzen. +-- Schreiben Sie jeweils eine generische Fassung, +-- welche nur die Monaden-Instanz oder, wenn möglich, +-- nur Applicative voraussetzt: + +-- b1) Beispiel: +multEnt :: (Num b) => (Entweder a b) -> (Entweder a b) -> (Entweder a b) +multEnt (Anderes x) (Anderes y) = Anderes (x * y) +multEnt (Anderes _) other = other +multEnt other _ = other + + +multEnt_M :: (Num b, Monad m) => m b -> m b -> m b +multEnt_M = multEnt_A -- The monad-applicative proposal was implemented ;-) + +multEnt_A :: (Num b, Applicative f) => f b -> f b -> f b +multEnt_A a b = (*) <$> a <*> b + + +-- b2) +foo :: (Entweder a (b->c)) -> (Entweder a b) -> (Entweder a c) +foo (Anderes f) (Anderes x) = Anderes $ f x +foo (Eines a) _ = Eines a +foo _ (Eines a) = Eines a + +foo_M :: (Monad m) => (m (b->c)) -> (m b) -> (m c) +foo_M = foo_A + +foo_A :: (Applicative m) => (m (b->c)) -> (m b) -> (m c) +foo_A f x = ($) <$> f <*> x + + +-- b3) +ifM :: (Entweder a Bool) -> (Entweder a b) -> (Entweder a b) -> (Entweder a b) +ifM (Anderes True) x _ = x +ifM (Anderes False) _ y = y +ifM (Eines a) _ _ = Eines a + +ifM_M :: (Monad m) => m Bool -> m b -> m b -> m b +ifM_M = ifM_A +ifM_A :: (Applicative f) => f Bool -> f b -> f b -> f b +ifM_A b x y = bool <$> x <*> y <*> b + + + +bool :: a -> a -> Bool -> a +-- ^ This should really be in Prelude (Data.Bool at least) +bool x _ True = x +bool _ x False = x + + + +---- A6-3 Do - Notation +-- +-- Implementieren Sie folgende Funktion unter Verwendung der Do-Notation: +-- Hinweis: Einfach den Typen folgen, alles andere kommt von allein! + +filterM :: Monad m => (a -> m Bool) -> [a] -> m [a] +filterM p = foldr trav (return []) + where + trav x xs = bool (x :) id <$> p x <*> xs -- Applicative is cooler than do notation ;-) + + trav' x xs = do -- But if I must … + include <- p x + xs' <- xs + return $ case include of + True -> x : xs' + False -> xs' + +-- Beispiele zum Testen: +silly1 :: Int -> Maybe Bool +silly1 0 = Nothing +silly1 x = Just $ even x + +silly2 :: Int -> [Bool] +silly2 0 = [] +silly2 x | even x = [False,True,True,False] + | otherwise = [False,False] + +-- > filterM silly [1..10] +-- Just [2,4,6,8,10] + +-- > filterM silly $ [1..10]++[1,0,1] +-- Nothing + -- cgit v1.2.3