git.iko.soy/Haskell-HSE/haskell-lectures-2024
on main help sign in
163 lines 3.6 kB history raw
1# Monad classes
3For now, consider the following monad transformers together with base Identity
4monad:
6```haskell
7class MonadTrans t where
8 lift :: m a -> t m a
10newtype ReaderT e m a = ReaderT { runReaderT :: e -> m a }
12instance Functor f => Functor (ReaderT e f)
14instance Applicative f => Applicative (ReaderT e f)
16instance Monad m => Monad (ReaderT e m)
18instance MonadTrans (ReaderT e)
20newtype WriterT w m a = WriterT { runWriterT :: m (w, a) }
22instance Functor f => Functor (WriterT w f)
24instance (Monoid w, Applicative f) => Applicative (WriterT w f)
26instance (Monoid w, Monad m) => Monad (WriterT w m)
28instance Monoid w => MonadTrans (WriterT w)
30newtype Identity a = Identity { runIdentity :: a }
32instance Functor Identity
34instance Applicative Identity
36instance Monad Identity
38type MyMonad = ReaderT Int (WriterT String Identity)
39```
41Using transformers, we can compose several effects together, but if you try to
42write a simple program with them, it will look like the following:
44```haskell
45myProgram :: MyMonad Int
46myProgram = do
47 env <- ReaderT (\env -> return env)
48 lift (WriterT (return (show env, ())))
49 return env
50```
52See how littered this is with different kinds of piping: `return`s, `lift`s,
53monad constructors etc. Using some auxiliary functions, program becomes a lot
54cleaner:
56```haskell
57ask0 :: Monad m => ReaderT e m e
58ask0 = ReaderT return
60write0 :: (Monoid w, Monad m) => w -> WriterT w m ()
61write0 w = WriterT (return (w, ()))
63myProgram' :: MyMonad Int
64myProgram' = do
65 env <- ask0
66 lift $ write0 (show env)
67 return env
68```
70```haskell
71newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
73instance Functor f => Functor (MaybeT f)
75instance Applicative f => Applicative (MaybeT f)
77instance Monad f => Monad (MaybeT f)
79instance MonadTrans MaybeT
81type ExtMonad a = MaybeT MyMonad a
83exit0 :: Monad m => MaybeT m a
84exit0 = MaybeT (return Nothing)
86divCtx :: Int -> ExtMonad Int
87divCtx x = do
88 y <- lift myProgram
89 if y == 0 then exit0 else return (x `div` y)
91divRed :: Int -> MaybeT (ReaderT Int Identity) Int
92divRed x = do
93 y <- lift ask0
94 if y == 0 then exit0 else return (x `div` y)
96-- use :: ExtMonad Int
97-- use = divRed 5
98```
100```haskell
101class Monad m => MonadWriterProto w m where
102 writeProto :: (a, w) -> m a
103 -- effectively same as w -> m ()
104 unfoldWriteProto :: m a -> m (a, w) -- ??
105 -- effectively same as m a -> m w
107class Monad m => MonadReaderProto e m where
108 readProto :: (e -> a) -> m a
109 readProto f = fmap f askProto
111 askProto :: m e
112 unfold :: m a -> (e -> m a)
114 localProto :: (e -> e) -> m a -> m a
115 localProto f x = do
116 e <- askProto
117 unfold x (f e)
118```
120```haskell
121class Monad m => MonadWriter w m where
122 write :: w -> m ()
124instance (Monad m, Monoid w) => MonadWriter w (WriterT w m) where
125 write = write0
127instance MonadWriter w m => MonadWriter w (ReaderT e m) where
128 write = lift . write
130instance MonadWriter w m => MonadWriter w (MaybeT m) where
131 write = lift . write
133class Monad m => MonadReader e m where
134 ask :: m e
135 local :: (e -> e) -> m a -> m a
137instance MonadReader e ((->) e) where
138 ask = id
139 local f g e = g (f e)
141instance Monad m => MonadReader e (ReaderT e m) where
142 ask = ask0
143 local f = undefined
145class Monad m => MonadMaybe m where
146 exit :: m a
148instance MonadMaybe Maybe where
149 exit = Nothing
151instance Monad m => MonadMaybe (MaybeT m) where
152 exit = exit0
153```
155```haskell
156myProgram'' :: (MonadReader Int m, MonadWriter String m) => m Int
157myProgram'' = do
158 env <- ask
159 write (show env)
160 return env
161```
163TAGLESS FINAL