Vorlesung2016/Übungen/Blatt3.solution.hs
Stefan Dresselhaus ff4826cc23
Added solutions for Blatt 3 & Blatt 5
To compile and run Blatt5 just do a "stack build" and either

stack exec Blatt5-static

or

stack exec Blatt5-animated
2016-07-25 04:05:30 +02:00

172 lines
4.2 KiB
Haskell

-- Übungsblatt 3
-- =============
--
-- Throat-Clearing
-- ---------------
--
-- a.k.a. Imports, damit der Code funktioniert.
module MonadExercise where
import Control.Applicative()
import Control.Monad()
import Data.Monoid
-- Vorwort
-- -------
--
-- Die Typklassen, die auf diesem Zettel implementiert werden sollen sind
-- teilweise nicht eindeutig. Ein gutes *Indiz* für eine falsche
-- implementation kann sein, dass Informationen "weggeschmissen" werden -
-- allerdings muss man bei anderen Implementationen genau dies machen.
--
-- Applicative
-- -----------
--
-- Nachdem wir uns letzte Woche ausführlich mit der Typklasse `Functor`
-- beschäftigt haben, bauen wir nun darauf auf und definieren die
-- Applicative-Instanz. Zur Erinnerung:
--
-- class Functor f => Applicative f where
-- pure :: a -> f a
-- <*> :: f (a -> b) -> f a -> f b
--
-- Nehmen sie an, sie hätten folgende Datentypen mit ihren
-- `Functor`-Instanzen gegeben. Schreiben sie jeweils die
-- Applicative-Instanz:
data Identity a = Identity { unIdentity :: a }
deriving (Show, Eq)
instance Functor Identity where
fmap f (Identity a) = Identity (f a)
instance Applicative Identity where
pure = Identity
(Identity f) <*> (Identity x) = Identity (f x)
instance Monad Identity where
return = pure
(Identity x) >>= f = f x
data Vielleicht a = Etwas a
| Nichts
deriving (Show, Eq)
instance Functor Vielleicht where
fmap f (Etwas a) = Etwas (f a)
fmap _ Nichts = Nichts
instance Applicative Vielleicht where
pure = Etwas
(Etwas f) <*> x = f <$> x
Nichts <*> _ = Nichts
instance Monad Vielleicht where
return = pure
(Etwas a) >>= f = f a
Nichts >>= _ = Nichts
data EntwederOder b a = Entweder a
| Oder b
deriving (Show, Eq)
instance Functor (EntwederOder b) where
fmap f (Entweder a) = Entweder (f a)
fmap _ (Oder b) = Oder b
instance Applicative (EntwederOder b) where
pure = Entweder
(Entweder f) <*> x = f <$> x
(Oder e) <*> _ = Oder e
instance Monad (EntwederOder b) where
return = pure
(Entweder x) >>= f = f x
(Oder e) >>= _ = Oder e
data List a = Cons a (List a)
| Nil
deriving (Show, Eq)
instance Functor List where
fmap f (Cons a r) = Cons (f a) (fmap f r)
fmap _ Nil = Nil
instance Monoid (List a) where
mempty = Nil
mappend Nil bs = bs
mappend (Cons a as) bs = Cons a (mappend as bs)
instance Applicative List where
pure a = Cons a Nil
Nil <*> _ = Nil
(Cons f fs) <*> x = (f <$> x) <> (fs <*> x)
instance Monad List where
return = pure
Nil >>= _ = Nil
(Cons x xs) >>= f = f x <> (xs >>= f)
data V3 a = V3 a a a
instance Functor V3 where
fmap f (V3 x y z) = V3 (f x) (f y) (f z)
instance Applicative V3 where
pure a = V3 a a a
(V3 f g h) <*> (V3 x y z) = V3 (f x) (g y) (h z)
instance Monad V3 where
return = pure
(V3 x y z) >>= f = V3 a b c
where
(V3 a _ _) = f x
(V3 _ b _) = f y
(V3 _ _ c) = f z
-- Monad
-- -----
--
-- Zu welchen der oben aufgeführten Typen gibt es eine Monaden-Instanz? Wie
-- sieht diese aus? Schreiben sie diese (falls möglich).
--
-- Bonus
-- -----
data Account = Account
data Inbox = Inbox
data Mail = Mail
-- Seien folgende Funktionen gegeben:
login :: Maybe Account
login = undefined
getInbox :: Account -> Maybe Inbox
getInbox = undefined
getMails :: Inbox -> [Mail]
getMails = undefined
safeHead :: [a] -> Maybe a
safeHead = undefined
-- Schreiben sie eine Funktion:
getFirstMail :: Maybe Mail
getFirstMail = do
a <- login
i <- getInbox a
safeHead $ getMails i
getFirstMail' :: Maybe Mail
getFirstMail' = login >>= getInbox >>= safeHead . getMails
-- welche die oben genannten 4 Funktionen nutzt um die erste Mail aus dem
-- gegebenen Account zurückzuliefern, sofern alles erfolgreich war.
--
-- Können sie beide Varianten (einmal mittels `do`-notation und einmal mit
-- `>>=`) schreiben?