-
Notifications
You must be signed in to change notification settings - Fork 0
/
ch26monadtrans.hs
149 lines (109 loc) · 3.74 KB
/
ch26monadtrans.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
{-# LANGUAGE InstanceSigs #-}
module Chapter26MonadTrans where
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.Trans.Class
import Control.Monad.Trans.Except
-- 26.2 MaybeT
newtype MaybeT m a =
MaybeT { runMaybeT :: m (Maybe a) }
instance (Functor m) => Functor (MaybeT m) where
fmap f (MaybeT ma) = MaybeT $ (fmap . fmap) f ma
instance (Applicative m) => Applicative (MaybeT m) where
pure a = MaybeT $ pure $ pure a
MaybeT fmab <*> MaybeT ma = MaybeT $ fmap (<*>) fmab <*> ma
instance (Monad m) => Monad (MaybeT m) where
fail _ = MaybeT $ pure Nothing
return = pure
(MaybeT mma) >>= famb = MaybeT $ do
ma <- mma
case ma of
Nothing -> return Nothing
Just a -> runMaybeT $ famb a
-- test MaybeT
mt0 :: MaybeT IO String
mt0 = do
liftIO $ print "Hola"
--fail ""
return "mt0"
mt1 :: MaybeT IO String
mt1 = do
liftIO $ print "Mundo"
return "mt1"
main :: IO ()
main = do
mss <- runMaybeT $ mt0 >> mt1
print mss
return ()
-- 26.3 EitherT
newtype EitherT e m a =
EitherT { runEitherT :: m (Either e a) }
instance (Functor m) => Functor (EitherT e m) where
fmap f (EitherT mea) = EitherT $ (fmap . fmap) f mea
instance (Applicative m) => Applicative (EitherT e m) where
pure a = EitherT $ pure $ Right a
(EitherT mef) <*> (EitherT mea) = EitherT $ fmap (<*>) mef <*> mea
instance (Monad m) => Monad (EitherT e m) where
fail = EitherT . fail
return = pure
(EitherT mea) >>= f = EitherT $ do
ea <- mea
case ea of
Left e -> return $ Left e
Right a -> runEitherT $ f a
swapEither :: Either e a -> Either a e
swapEither (Left e) = Right e
swapEither (Right a) = Left a
swapEitherT :: (Functor m) => EitherT e m a -> EitherT a m e
swapEitherT (EitherT mea) = EitherT $ fmap swapEither mea
eitherT :: Monad m =>
(a -> m c)
-> (b -> m c)
-> EitherT a m b
-> m c
eitherT famc fbmc (EitherT mab) = do
ab <- mab
case ab of
Left a -> famc a
Right b -> fbmc b
-- 26.4 ReaderT
newtype ReaderT r m a =
ReaderT { runReaderT :: r -> m a }
instance (Functor m) => Functor (ReaderT r m) where
fmap f (ReaderT rma) = ReaderT $ (fmap . fmap) f rma
instance (Applicative m) => Applicative (ReaderT r m) where
pure a = ReaderT $ pure $ pure a
(ReaderT rmf) <*> (ReaderT rma) = ReaderT $ fmap (<*>) rmf <*> rma
instance (Monad m) => Monad (ReaderT r m) where
return = pure
(ReaderT rma) >>= f = ReaderT $ \r -> rma r >>= (\a -> (runReaderT $ f a) r)
-- 26.5 StateT
newtype StateT s m a =
StateT { runStateT :: s -> m (a, s) }
first :: (a -> b) -> (a, s) -> (b, s)
first f (a, s) = (f a, s)
instance (Functor m) => Functor (StateT s m) where
fmap f (StateT smas) = StateT $ (fmap . fmap) (first f) smas
instance (Monad m) => Applicative (StateT s m) where
pure a = StateT $ \s -> pure (a, s)
(StateT smfs) <*> (StateT smas) = StateT $ smfs >=> \(f,s) -> fmap (first f) (smas s)
instance (Monad m) => Monad (StateT s m) where
return = pure
(StateT smas) >>= f = StateT $ smas >=> \(a,s) -> runStateT (f a) s
-- 26.8 Lexically inner is structurally outer: Wrap it up
embedded :: MaybeT (ExceptT String (ReaderT () IO)) Int
embedded = MaybeT $ ExceptT $ ReaderT (return . const (Right (Just 1)))
-- 26.9 Exercices: Lift More
instance MonadTrans (EitherT e) where
lift = EitherT . liftM Right
instance MonadTrans (StateT s) where
lift ma = StateT $ \s -> liftM (\a -> (a, s)) ma
-- 26.10 Exercices: Some Instances
liftMaybeT :: (Monad m) => m a -> MaybeT m a
liftMaybeT = MaybeT . liftM Just
instance (MonadIO m) => MonadIO (MaybeT m) where
liftIO = liftMaybeT . liftIO
instance (MonadIO m) => MonadIO (ReaderT r m) where
liftIO = ReaderT . const . liftIO
instance (MonadIO m) => MonadIO (StateT s m) where
liftIO = lift . liftIO