@@ -1,57 +1,11 @@
1−{-# OPTIONS_GHC -fno-warn-unticked-promoted-constructors #-}
2−
31{-# LANGUAGE DeriveGeneric #-}
4−{-# LANGUAGE TypeFamilies #-}
2+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
53{-# LANGUAGE FlexibleInstances #-}
64{-# LANGUAGE UndecidableInstances #-}
7−{-# LANGUAGE DataKinds #-}
8−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
9−
10−{- |
11−
12−Type-level machinery to manipulate constraints on the monad
13−transformer stack.
14−
15−Out of the box it provides the following dispatch strategies:
16−
17−* 'tagAttach' to use functions defined using untagged monad classes
18− as if they were defined using tagged ones.
19−
20−* 'tagReplace' to use functions defined using one tag
21− as if they were defined using another one.
22−
23−> import qualified Control.Monad.State as T
24−> import Control.Ether.TH (ethereal)
25−> import Control.Monad.Ether.State (MonadState)
26−> import Control.Monad.Trans.Ether.Dispatch (tagAttach, tagDispatch)
27−>
28−> ethereal "Foo" "foo"
29−> ethereal "Bar" "bar"
30−>
31−> f :: T.MonadState Int m => m String
32−> f = fmap show T.get
33−>
34−> g :: MonadState Foo Int m => m String
35−> g = tagAttach foo f
36−>
37−> h :: MonadState Bar Int m => m String
38−> h = tagReplace foo bar g
39−
40−-}
5+{-# LANGUAGE ConstraintKinds #-}
6+{-# LANGUAGE TypeFamilies #-}
417
42−module Control.Monad.Trans.Ether.Dispatch
43− (
44− -- * The DispatchT monad transformer
45− DispatchT
46− , dispatchT
47− , runDispatchT
48− , redispatch
49− -- * Dispatch types and functions
50− , K_TagAttach(..)
51− , tagAttach
52− , K_TagReplace(..)
53− , tagReplace
54− ) where
8+module Control.Monad.Trans.Ether.Dispatch where
559
5610import Control.Applicative
5711import Control.Monad (MonadPlus)
@@ -63,7 +17,6 @@ import Control.Monad.Catch (MonadThrow, MonadCatch, MonadMask)
6317
6418import qualified Control.Monad.Base as MB
6519import qualified Control.Monad.Trans.Control as MC
66−import qualified Control.Monad.Trans.Identity as Trans
6720
6821import qualified Control.Monad.Trans.Lift.StT as Lift
6922import qualified Control.Monad.Trans.Lift.Local as Lift
@@ -72,16 +25,6 @@ import qualified Control.Monad.Trans.Lift.Listen as Lift
7225import qualified Control.Monad.Trans.Lift.Pass as Lift
7326import qualified Control.Monad.Trans.Lift.CallCC as Lift
7427
75−import Control.Monad.Ether.Reader.Class
76−import Control.Monad.Ether.State.Class
77−import Control.Monad.Ether.Except.Class
78−import Control.Monad.Ether.Writer.Class
79−
80−import Control.Monad.Ether.Reader as A
81−import Control.Monad.Ether.State.Common as A
82−import Control.Monad.Ether.Except as A
83−import Control.Monad.Ether.Writer as A
84−
8528import qualified Control.Monad.Cont.Class as Class
8629import qualified Control.Monad.Reader.Class as Class
8730import qualified Control.Monad.State.Class as Class
@@ -91,84 +34,75 @@ import qualified Control.Monad.Error.Class as Class
9134import GHC.Generics (Generic)
9235import Data.Coerce (coerce)
9336
94−-- | Wrap a monad to change its tags. Under the hood this is
95−-- simply 'Trans.IdentityT', all the work is happening on the type level.
96−newtype DispatchT dp m a = DispatchT (Trans.IdentityT m a)
37+newtype Dispatch dp trans m a = Dispatch (trans m a)
9738 deriving
9839 ( Generic
9940 , Functor, Applicative, Alternative, Monad, MonadPlus
10041 , MonadFix, MonadTrans, MonadIO, MFunctor, MMonad
10142 , MonadThrow, MonadCatch, MonadMask )
10243
103−-- | Type-restricted 'coerce'.
104−pack :: forall dp m a . Trans.IdentityT m a -> DispatchT dp m a
44+pack :: forall dp trans m a . trans m a -> Dispatch dp trans m a
10545pack = coerce
10646{-# INLINE pack #-}
10747
108−-- | Type-restricted 'coerce'.
109−unpack :: forall dp m a . DispatchT dp m a -> Trans.IdentityT m a
48+unpack :: forall dp trans m a . Dispatch dp trans m a -> trans m a
11049unpack = coerce
11150{-# INLINE unpack #-}
11251
113−-- | Type-restricted 'coerce'.
114−dispatchT :: forall dp m a . m a -> DispatchT dp m a
115−dispatchT = coerce
116−{-# INLINE dispatchT #-}
117−
118−-- | Type-restricted 'coerce'.
119−runDispatchT :: forall dp m a . DispatchT dp m a -> m a
120−runDispatchT = coerce
121−{-# INLINE runDispatchT #-}
52+repack :: forall dp dp' trans m a . Dispatch dp trans m a -> Dispatch dp' trans m a
53+repack = coerce
54+{-# INLINE repack #-}
12255
123−-- | Type-restricted 'coerce'.
124−redispatch :: forall dp dp' m a . DispatchT dp m a -> DispatchT dp' m a
125−redispatch = coerce
126−{-# INLINE redispatch #-}
127−
128−instance MB.MonadBase b m => MB.MonadBase b (DispatchT dp m) where
129− liftBase = MB.liftBaseDefault
130−
131−instance MC.MonadTransControl (DispatchT dp) where
132− type StT (DispatchT dp) a = MC.StT Trans.IdentityT a
133− liftWith = MC.defaultLiftWith pack unpack
134− restoreT = MC.defaultRestoreT pack
56+instance
57+ ( MB.MonadBase b m
58+ , MonadTrans trans
59+ , Monad (trans m)
60+ ) => MB.MonadBase b (Dispatch dp trans m)
61+ where
62+ liftBase = MB.liftBaseDefault
13563
136−instance MC.MonadBaseControl b m => MC.MonadBaseControl b (DispatchT dp m) where
137− type StM (DispatchT dp m) a = MC.ComposeSt (DispatchT dp) m a
138− liftBaseWith = MC.defaultLiftBaseWith
139− restoreM = MC.defaultRestoreM
64+instance
65+ ( MC.MonadTransControl trans
66+ ) => MC.MonadTransControl (Dispatch dp trans)
67+ where
68+ type StT (Dispatch dp trans) a = MC.StT trans a
69+ liftWith = MC.defaultLiftWith pack unpack
70+ restoreT = MC.defaultRestoreT pack
14071
141−type instance Lift.StT (DispatchT dp) a = MC.StT (DispatchT dp) a
72+type instance Lift.StT (Dispatch dp trans) a = Lift.StT trans a
14273
143−instance Lift.LiftLocal (DispatchT dp) where
74+instance Lift.LiftLocal trans => Lift.LiftLocal (Dispatch dp trans) where
14475 liftLocal = Lift.defaultLiftLocal pack unpack
14576
146−instance Lift.LiftCatch (DispatchT dp) where
77+instance Lift.LiftCatch trans => Lift.LiftCatch (Dispatch dp trans) where
14778 liftCatch = Lift.defaultLiftCatch pack unpack
14879
149−instance Lift.LiftListen (DispatchT dp) where
80+instance Lift.LiftListen trans => Lift.LiftListen (Dispatch dp trans) where
15081 liftListen = Lift.defaultLiftListen pack unpack
15182
152−instance Lift.LiftPass (DispatchT dp) where
83+instance Lift.LiftPass trans => Lift.LiftPass (Dispatch dp trans) where
15384 liftPass = Lift.defaultLiftPass pack unpack
15485
155−instance Lift.LiftCallCC (DispatchT dp) where
86+instance Lift.LiftCallCC trans => Lift.LiftCallCC (Dispatch dp trans) where
15687 liftCallCC = Lift.defaultLiftCallCC pack unpack
15788 liftCallCC' = Lift.defaultLiftCallCC' pack unpack
15889
90+
15991-- Instances for mtl classes
16092
16193instance {-# OVERLAPPABLE #-}
16294 ( Class.MonadCont m
163− , Monad m
164− ) => Class.MonadCont (DispatchT dp m)
95+ , Lift.LiftCallCC trans
96+ , Monad (trans m)
97+ ) => Class.MonadCont (Dispatch dp trans m)
16598 where
16699 callCC = Lift.liftCallCC' Class.callCC
167100
168101instance {-# OVERLAPPABLE #-}
169102 ( Class.MonadReader r m
170− , Monad m
171− ) => Class.MonadReader r (DispatchT dp m)
103+ , Lift.LiftLocal trans
104+ , Monad (trans m)
105+ ) => Class.MonadReader r (Dispatch dp trans m)
172106 where
173107 ask = lift Class.ask
174108 local = Lift.liftLocal Class.ask Class.local
@@ -176,8 +110,9 @@ instance {-# OVERLAPPABLE #-}
176110
177111instance {-# OVERLAPPABLE #-}
178112 ( Class.MonadState s m
179− , Monad m
180− ) => Class.MonadState s (DispatchT dp m)
113+ , MonadTrans trans
114+ , Monad (trans m)
115+ ) => Class.MonadState s (Dispatch dp trans m)
181116 where
182117 get = lift Class.get
183118 put = lift . Class.put
@@ -185,8 +120,10 @@ instance {-# OVERLAPPABLE #-}
185120
186121instance {-# OVERLAPPABLE #-}
187122 ( Class.MonadWriter w m
188− , Monad m
189− ) => Class.MonadWriter w (DispatchT dp m)
123+ , Lift.LiftListen trans
124+ , Lift.LiftPass trans
125+ , Monad (trans m)
126+ ) => Class.MonadWriter w (Dispatch dp trans m)
190127 where
191128 writer = lift . Class.writer
192129 tell = lift . Class.tell
@@ -195,76 +132,9 @@ instance {-# OVERLAPPABLE #-}
195132
196133instance {-# OVERLAPPABLE #-}
197134 ( Class.MonadError e m
198− , Monad m
199− ) => Class.MonadError e (DispatchT dp m)
135+ , Lift.LiftCatch trans
136+ , Monad (trans m)
137+ ) => Class.MonadError e (Dispatch dp trans m)
200138 where
201139 throwError = lift . Class.throwError
202140 catchError = Lift.liftCatch Class.catchError
203−
204−
205−-- TagAttach
206−
207−-- | Encode type-level information for 'tagAttach'.
208−data K_TagAttach t = TagAttach t
209−
210−type DispatchTagAttachT t = DispatchT (TagAttach t)
211−
212−-- | Attach a tag to untagged transformers.
213−tagAttach :: forall tag m a . DispatchTagAttachT tag m a -> m a
214−tagAttach = runDispatchT
215−
216−instance MonadReader tag r m
217− => Class.MonadReader r (DispatchTagAttachT tag m) where
218− ask = Lift.lift (A.ask @tag)
219− local = Lift.liftLocal (A.ask @tag) (A.local @tag)
220−
221−instance MonadState tag s m
222− => Class.MonadState s (DispatchTagAttachT tag m) where
223− get = Lift.lift (A.get @tag)
224− put = Lift.lift . A.put @tag
225−
226−instance MonadExcept tag e m
227− => Class.MonadError e (DispatchTagAttachT tag m) where
228− throwError = Lift.lift . A.throw @tag
229− catchError = Lift.liftCatch (A.catch @tag)
230−
231−instance MonadWriter tag w m
232− => Class.MonadWriter w (DispatchTagAttachT tag m) where
233− writer = Lift.lift . A.writer @tag
234− tell = Lift.lift . A.tell @tag
235− listen = Lift.liftListen (A.listen @tag)
236− pass = Lift.liftPass (A.pass @tag)
237−
238−
239−-- TagReplace
240−
241−-- | Encode type-level information for 'tagReplace'.
242−data K_TagReplace tOld tNew = TagReplace tOld tNew
243−
244−type DispatchTagReplaceT tOld tNew = DispatchT (TagReplace tOld tNew)
245−
246−-- | Replace a tag with another tag.
247−tagReplace :: forall tOld tNew m a . DispatchTagReplaceT tOld tNew m a -> m a
248−tagReplace = runDispatchT
249−
250−instance MonadReader tNew r m
251− => MonadReader tOld r (DispatchTagReplaceT tOld tNew m) where
252− ask _ = Lift.lift (A.ask @tNew)
253− local _ = Lift.liftLocal (A.ask @tNew) (A.local @tNew)
254−
255−instance MonadState tNew s m
256− => MonadState tOld s (DispatchTagReplaceT tOld tNew m) where
257− get _ = Lift.lift (A.get @tNew)
258− put _ = Lift.lift . A.put @tNew
259−
260−instance MonadExcept tNew e m
261− => MonadExcept tOld e (DispatchTagReplaceT tOld tNew m) where
262− throw _ = Lift.lift . A.throw @tNew
263− catch _ = Lift.liftCatch (A.catch @tNew)
264−
265−instance MonadWriter tNew w m
266− => MonadWriter tOld w (DispatchTagReplaceT tOld tNew m) where
267− writer _ = Lift.lift . A.writer @tNew
268− tell _ = Lift.lift . A.tell @tNew
269− listen _ = Lift.liftListen (A.listen @tNew)
270− pass _ = Lift.liftPass (A.pass @tNew)