on master help sign in
DispatchT and other stuff
commit4b2f1850a661dd6267652352d8f987a6b1d5d513 authorIndex Int <vlad.z.4096@gmail.com> dateSat 12 Dec 2015, 19:32 (11 years ago) parentfa27ac9
20 files changed+319−238
.travis.yml+2−2 CHANGELOG.md+2−1 ether.cabal+16−3 src/Control/Ether/Wrapped.hs−102 src/Control/Monad/Ether.hs+9−18 src/Control/Monad/Ether/Except/Class.hs+6−7 src/Control/Monad/Ether/Implicit.hs+9−14 src/Control/Monad/Ether/Reader/Class.hs+6−7 src/Control/Monad/Ether/State/Class.hs+10−11 src/Control/Monad/Ether/Writer/Class.hs+6−7 src/Control/Monad/Trans/Ether/Dispatch.hs+184 src/Control/Monad/Trans/Ether/Except.hs+2−2 src/Control/Monad/Trans/Ether/Reader.hs+2−2 src/Control/Monad/Trans/Ether/State/Lazy.hs+2−2 src/Control/Monad/Trans/Ether/State/Strict.hs+2−2 src/Control/Monad/Trans/Ether/Writer.hs+2−2 stack-ghc-7.8.4.yaml+1 test/Regression.hs+11−56 test/Regression/T1.hs+39 test/Regression/T2.hs+8
.travis.yml+2−2
@@ -2,7 +2,7 @@ sudo: false
22
33env:
44 - CABALVER=1.18 GHCVER=7.8.4
5− - CABALVER=1.22 GHCVER=7.10.1
5+ - CABALVER=1.22 GHCVER=7.10.3
66
77before_install:
88 - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
@@ -24,6 +24,6 @@ addons:
2424 - hvr-ghc
2525 packages:
2626 - ghc-7.8.4
27− - ghc-7.10.1
27+ - ghc-7.10.3
2828 - cabal-install-1.18
2929 - cabal-install-1.22
CHANGELOG.md+2−1
@@ -1,9 +1,10 @@
110.4.0.0
22-------
33
4+* Poly-kinded tags.
45* Remove `Control.Ether.Tagged`.
6+* Replace `Control.Ether.Wrapped` with `Control.Monad.Trans.Ether.Dispatch`.
57* `MonadThrow`, `MonadCatch`, `MonadMask` instances.
6−* `MonadBase`, `MonadBaseControl` for `WrapEther`.
78* Drop `newtype-generics`.
89
910
ether.cabal+16−3
@@ -24,8 +24,7 @@ source-repository head
2424
2525library
2626
27− exposed-modules: Control.Ether.Wrapped
28− Control.Ether.Abbr
27+ exposed-modules: Control.Ether.Abbr
2928 Control.Ether.Implicit.Abbr
3029 Control.Ether.TH
3130 Control.Monad.Trans.Ether.Reader
@@ -34,6 +33,7 @@ library
3433 Control.Monad.Trans.Ether.State.Lazy
3534 Control.Monad.Trans.Ether.State.Strict
3635 Control.Monad.Trans.Ether.Except
36+ Control.Monad.Trans.Ether.Dispatch
3737 Control.Monad.Ether
3838 Control.Monad.Ether.Reader
3939 Control.Monad.Ether.Reader.Class
@@ -97,7 +97,20 @@ test-suite regression
9797 , ether
9898
9999 main-is: Regression.hs
100+ other-modules: Regression.T1
101+ Regression.T2
102+
100103 type: exitcode-stdio-1.0
101104 hs-source-dirs: test
102105 default-language: Haskell2010
103− ghc-options: -Wall
106+ default-extensions: TypeFamilies
107+ FlexibleContexts
108+ EmptyDataDecls
109+ TemplateHaskell
110+ ConstraintKinds
111+ ScopedTypeVariables
112+ DataKinds
113+ PolyKinds
114+ TypeOperators
115+ LambdaCase
116+ ghc-options: -Wall -fno-warn-missing-signatures
src/Control/Ether/Wrapped.hsdeleted−102
@@ -1,102 +0,0 @@
1−{-# LANGUAGE DeriveGeneric #-}
2−{-# LANGUAGE MultiParamTypeClasses #-}
3−{-# LANGUAGE FlexibleInstances #-}
4−{-# LANGUAGE UndecidableInstances #-}
5−{-# LANGUAGE ScopedTypeVariables #-}
6−{-# LANGUAGE TypeFamilies #-}
7−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
8−
9−{- |
10−Annotating monads with tags to turn untagged constraints into tagged ones.
11−
12−> import qualified Control.Monad.State as T
13−> import Control.Ether.TH (ethereal)
14−> import Control.Monad.Ether.State (MonadState)
15−> import Control.Ether.Wrapped (ethered)
16−>
17−> ethereal "Foo" "foo"
18−>
19−> f :: T.MonadState Int m => m String
20−> f = fmap show T.get
21−>
22−> g :: MonadState Foo Int m => m String
23−> g = ethered foo f
24−-}
25−
26−module Control.Ether.Wrapped
27− ( WrappedEther(..)
28− , ethered
29− ) where
30−
31−import Data.Proxy (Proxy(Proxy))
32−import Control.Applicative
33−import Control.Monad (MonadPlus)
34−import Control.Monad.Fix (MonadFix)
35−import Control.Monad.IO.Class (MonadIO)
36−import GHC.Generics (Generic)
37−import Data.Coerce (coerce)
38−
39−import Control.Monad.Ether.Reader.Class
40−import Control.Monad.Ether.State.Class
41−import Control.Monad.Ether.Except.Class
42−import Control.Monad.Ether.Writer.Class
43−
44−import qualified Control.Monad.Reader as Class
45−import qualified Control.Monad.State as Class
46−import qualified Control.Monad.Except as Class
47−import qualified Control.Monad.Writer as Class
48−
49−import qualified Control.Monad.Base as MB
50−import qualified Control.Monad.Trans.Control as MC
51−
52−-- | Wrap a monad to attach a tag to it.
53−newtype WrappedEther tag m a = WrapEther { unwrapEther :: m a }
54− deriving ( Generic
55− , Functor, Applicative, Alternative, Monad, MonadPlus
56− , MonadFix, MonadIO )
57−
58−-- | Annotate a polymorphic monadic computation with a tag.
59−ethered :: proxy tag -> WrappedEther tag m a -> m a
60−ethered _proxy = coerce
61−
62−instance MB.MonadBase b m => MB.MonadBase b (WrappedEther tag m) where
63− liftBase a = WrapEther (MB.liftBase a)
64−
65−instance MC.MonadBaseControl b m => MC.MonadBaseControl b (WrappedEther tag m) where
66− type StM (WrappedEther tag m) a = MC.StM m a
67− liftBaseWith a = WrapEther (MC.liftBaseWith (a . coerce))
68− restoreM a = WrapEther (MC.restoreM a)
69−
70−instance MonadReader tag r m => Class.MonadReader r (WrappedEther tag m) where
71− ask = WrapEther $ ask (Proxy :: Proxy tag)
72− local f = WrapEther . local (Proxy :: Proxy tag) f . coerce
73−
74−instance MonadReader tag r m => MonadReader tag r (WrappedEther tag' m) where
75− ask t = WrapEther $ ask t
76− local t f = WrapEther . local t f . coerce
77−
78−instance MonadState tag s m => Class.MonadState s (WrappedEther tag m) where
79− get = WrapEther $ get (Proxy :: Proxy tag)
80− put = WrapEther . put (Proxy :: Proxy tag)
81−
82−instance MonadState tag s m => MonadState tag s (WrappedEther tag' m) where
83− get t = WrapEther $ get t
84− put t = WrapEther . put t
85−
86−instance MonadExcept tag e m => Class.MonadError e (WrappedEther tag m) where
87− throwError = WrapEther . throw (Proxy :: Proxy tag)
88− catchError m h = WrapEther $ catch (Proxy :: Proxy tag) (coerce m) (coerce . h)
89−
90−instance MonadExcept tag e m => MonadExcept tag e (WrappedEther tag' m) where
91− throw t = WrapEther . throw t
92− catch t m h = WrapEther $ catch t (coerce m) (coerce . h)
93−
94−instance MonadWriter tag w m => Class.MonadWriter w (WrappedEther tag m) where
95− tell = WrapEther . tell (Proxy :: Proxy tag)
96− listen = WrapEther . listen (Proxy :: Proxy tag) . coerce
97− pass = WrapEther . pass (Proxy :: Proxy tag) . coerce
98−
99−instance MonadWriter tag w m => MonadWriter tag w (WrappedEther tag' m) where
100− tell t = WrapEther . tell t
101− listen t = WrapEther . listen t . coerce
102− pass t = WrapEther . pass t . coerce
src/Control/Monad/Ether.hs+9−18
@@ -2,22 +2,13 @@
22-- | This module provides convenience exports of all
33-- tagged monad classes from Ether.
44
5−module Control.Monad.Ether
6− ( module Control.Monad
7− , module Control.Monad.Fix
8− , module Control.Monad.Ether.Reader
9− , module Control.Monad.Ether.Writer
10− , module Control.Monad.Ether.State
11− , module Control.Monad.Ether.Except
12− , module Control.Ether.Wrapped
13− , ethereal
14− ) where
5+module Control.Monad.Ether (module X) where
156
16−import Control.Monad
17−import Control.Monad.Fix
18−import Control.Monad.Ether.Reader
19−import Control.Monad.Ether.Writer
20−import Control.Monad.Ether.State
21−import Control.Monad.Ether.Except
22−import Control.Ether.Wrapped
23−import Control.Ether.TH (ethereal)
7+import Control.Monad as X
8+import Control.Monad.Fix as X
9+import Control.Monad.Ether.Reader as X
10+import Control.Monad.Ether.Writer as X
11+import Control.Monad.Ether.State as X
12+import Control.Monad.Ether.Except as X
13+import Control.Monad.Trans.Ether.Dispatch as X hiding (pack, unpack)
14+import Control.Ether.TH as X (ethereal)
src/Control/Monad/Ether/Except/Class.hs+6−7
@@ -1,23 +1,22 @@
1+{-# LANGUAGE CPP #-}
2+
3+#if __GLASGOW_HASKELL__ < 710
4+{-# LANGUAGE OverlappingInstances #-}
15{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}
6+#endif
27
3−{-# LANGUAGE CPP #-}
48{-# LANGUAGE MultiParamTypeClasses #-}
59{-# LANGUAGE FlexibleInstances #-}
610{-# LANGUAGE UndecidableInstances #-}
711{-# LANGUAGE FunctionalDependencies #-}
812{-# LANGUAGE PolyKinds #-}
913
10−#if __GLASGOW_HASKELL__ < 710
11−{-# LANGUAGE OverlappingInstances #-}
12−#endif
13−
1414-- | See "Control.Monad.Except".
1515
1616module Control.Monad.Ether.Except.Class
1717 ( MonadExcept(..)
1818 ) where
1919
20−import Control.Monad.Trans.Ether.Except hiding (throw, catch)
2120import qualified Control.Monad.Trans.Ether.Except as E
2221import qualified Control.Monad.Trans.Lift.Catch as Lift
2322
@@ -32,7 +31,7 @@ class Monad m => MonadExcept tag e m | m tag -> e where
3231 -- normal execution.
3332 catch :: proxy tag -> m a -> (e -> m a) -> m a
3433
35−instance Monad m => MonadExcept tag e (ExceptT tag e m) where
34+instance Monad m => MonadExcept tag e (E.ExceptT tag e m) where
3635 throw = E.throw
3736 catch = E.catch
3837
src/Control/Monad/Ether/Implicit.hs+9−14
@@ -2,18 +2,13 @@
22-- | This module provides convenience exports of all
33-- implicitly tagged monad classes from Ether.
44
5−module Control.Monad.Ether.Implicit
6− ( module Control.Monad
7− , module Control.Monad.Fix
8− , module Control.Monad.Ether.Implicit.Reader
9− , module Control.Monad.Ether.Implicit.Writer
10− , module Control.Monad.Ether.Implicit.State
11− , module Control.Monad.Ether.Implicit.Except
12− ) where
5+module Control.Monad.Ether.Implicit (module X) where
136
14−import Control.Monad
15−import Control.Monad.Fix
16−import Control.Monad.Ether.Implicit.Reader
17−import Control.Monad.Ether.Implicit.Writer
18−import Control.Monad.Ether.Implicit.State
19−import Control.Monad.Ether.Implicit.Except
7+import Control.Monad as X
8+import Control.Monad.Fix as X
9+import Control.Monad.Ether.Implicit.Reader as X
10+import Control.Monad.Ether.Implicit.Writer as X
11+import Control.Monad.Ether.Implicit.State as X
12+import Control.Monad.Ether.Implicit.Except as X
13+import Control.Monad.Trans.Ether.Dispatch as X hiding (pack, unpack)
14+import Control.Ether.TH as X (ethereal)
src/Control/Monad/Ether/Reader/Class.hs+6−7
@@ -1,16 +1,16 @@
1+{-# LANGUAGE CPP #-}
2+
3+#if __GLASGOW_HASKELL__ < 710
4+{-# LANGUAGE OverlappingInstances #-}
15{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}
6+#endif
27
3−{-# LANGUAGE CPP #-}
48{-# LANGUAGE MultiParamTypeClasses #-}
59{-# LANGUAGE FlexibleInstances #-}
610{-# LANGUAGE UndecidableInstances #-}
711{-# LANGUAGE FunctionalDependencies #-}
812{-# LANGUAGE PolyKinds #-}
913
10−#if __GLASGOW_HASKELL__ < 710
11−{-# LANGUAGE OverlappingInstances #-}
12−#endif
13−
1414-- | See "Control.Monad.Reader.Class".
1515
1616module Control.Monad.Ether.Reader.Class
@@ -18,7 +18,6 @@ module Control.Monad.Ether.Reader.Class
1818 , asks
1919 ) where
2020
21−import Control.Monad.Trans.Ether.Reader hiding (reader, ask, local)
2221import qualified Control.Monad.Trans.Ether.Reader as R
2322import qualified Control.Monad.Trans.Lift.Local as Lift
2423import qualified Control.Ether.Util as Util
@@ -58,7 +57,7 @@ asks
5857 -> m a
5958asks = reader
6059
61−instance Monad m => MonadReader tag r (ReaderT tag r m) where
60+instance Monad m => MonadReader tag r (R.ReaderT tag r m) where
6261 ask = R.ask
6362 local = R.local
6463 reader = R.reader
src/Control/Monad/Ether/State/Class.hs+10−11
@@ -1,16 +1,16 @@
1+{-# LANGUAGE CPP #-}
2+
3+#if __GLASGOW_HASKELL__ < 710
4+{-# LANGUAGE OverlappingInstances #-}
15{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}
6+#endif
27
3−{-# LANGUAGE CPP #-}
48{-# LANGUAGE MultiParamTypeClasses #-}
59{-# LANGUAGE FlexibleInstances #-}
610{-# LANGUAGE UndecidableInstances #-}
711{-# LANGUAGE FunctionalDependencies #-}
812{-# LANGUAGE PolyKinds #-}
913
10−#if __GLASGOW_HASKELL__ < 710
11−{-# LANGUAGE OverlappingInstances #-}
12−#endif
13−
1414-- | See "Control.Monad.State.Class".
1515
1616module Control.Monad.Ether.State.Class
@@ -19,10 +19,9 @@ module Control.Monad.Ether.State.Class
1919 , gets
2020 ) where
2121
22−import Control.Monad.Trans (MonadTrans(..))
23−
2422import qualified Control.Monad.Trans.Ether.State.Lazy as S.L
2523import qualified Control.Monad.Trans.Ether.State.Strict as S.S
24+import qualified Control.Monad.Trans as Lift
2625import qualified Control.Ether.Util as Util
2726
2827-- | See 'Control.Monad.State.MonadState'.
@@ -65,10 +64,10 @@ instance Monad m => MonadState tag s (S.S.StateT tag s m) where
6564 state = S.S.state
6665
6766instance {-# OVERLAPPABLE #-}
68− ( MonadTrans t
67+ ( Lift.MonadTrans t
6968 , Monad (t m)
7069 , MonadState tag s m
7170 ) => MonadState tag s (t m) where
72− get t = lift (get t)
73− put t = lift . put t
74− state t = lift . state t
71+ get t = Lift.lift (get t)
72+ put t = Lift.lift . put t
73+ state t = Lift.lift . state t
src/Control/Monad/Ether/Writer/Class.hs+6−7
@@ -1,16 +1,16 @@
1+{-# LANGUAGE CPP #-}
2+
3+#if __GLASGOW_HASKELL__ < 710
4+{-# LANGUAGE OverlappingInstances #-}
15{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}
6+#endif
27
3−{-# LANGUAGE CPP #-}
48{-# LANGUAGE MultiParamTypeClasses #-}
59{-# LANGUAGE FlexibleInstances #-}
610{-# LANGUAGE UndecidableInstances #-}
711{-# LANGUAGE FunctionalDependencies #-}
812{-# LANGUAGE PolyKinds #-}
913
10−#if __GLASGOW_HASKELL__ < 710
11−{-# LANGUAGE OverlappingInstances #-}
12−#endif
13−
1414-- | See "Control.Monad.Writer.Class".
1515
1616module Control.Monad.Ether.Writer.Class
@@ -23,7 +23,6 @@ module Control.Monad.Ether.Writer.Class
2323import Data.Monoid
2424#endif
2525
26−import Control.Monad.Trans.Ether.Writer hiding (writer, tell, listen, pass)
2726import qualified Control.Monad.Trans.Ether.Writer as W
2827import qualified Control.Monad.Trans.Lift.Listen as Lift
2928import qualified Control.Monad.Trans.Lift.Pass as Lift
@@ -64,7 +63,7 @@ censor t f m = pass t $ do
6463 a <- m
6564 return (a, f)
6665
67−instance (Monoid w, Monad m) => MonadWriter tag w (WriterT tag w m) where
66+instance (Monoid w, Monad m) => MonadWriter tag w (W.WriterT tag w m) where
6867 writer = W.writer
6968 tell = W.tell
7069 listen = W.listen
src/Control/Monad/Trans/Ether/Dispatch.hsnew file+184
@@ -0,0 +1,184 @@
1+{-# LANGUAGE CPP #-}
2+
3+#if __GLASGOW_HASKELL__ >= 710
4+{-# OPTIONS_GHC -fno-warn-unticked-promoted-constructors #-}
5+#endif
6+
7+{-# LANGUAGE DeriveGeneric #-}
8+{-# LANGUAGE MultiParamTypeClasses #-}
9+{-# LANGUAGE TypeFamilies #-}
10+{-# LANGUAGE FlexibleInstances #-}
11+{-# LANGUAGE UndecidableInstances #-}
12+{-# LANGUAGE ScopedTypeVariables #-}
13+{-# LANGUAGE DataKinds #-}
14+{-# LANGUAGE PolyKinds #-}
15+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
16+
17+{- |
18+
19+-}
20+
21+module Control.Monad.Trans.Ether.Dispatch
22+ (
23+ -- * The DispatchT monad transformer
24+ DispatchT
25+ -- * Dispatch types and functions
26+ , K_TagAttach(..)
27+ , K_TagReplace(..)
28+ , tagAttach
29+ , tagReplace
30+ -- * Newtype operations
31+ , pack
32+ , unpack
33+ ) where
34+
35+import Control.Applicative
36+import Control.Monad (MonadPlus)
37+import Control.Monad.Fix (MonadFix)
38+import Control.Monad.Trans.Class (MonadTrans)
39+import Control.Monad.IO.Class (MonadIO)
40+import Control.Monad.Morph (MFunctor, MMonad)
41+import Control.Monad.Catch (MonadThrow, MonadCatch, MonadMask)
42+import GHC.Generics (Generic)
43+import Data.Coerce (coerce)
44+import Data.Proxy
45+
46+import qualified Control.Monad.Base as MB
47+import qualified Control.Monad.Trans.Control as MC
48+import qualified Control.Monad.Trans.Identity as Trans
49+
50+import qualified Control.Monad.Trans.Lift.StT as Lift
51+import qualified Control.Monad.Trans.Lift.Local as Lift
52+import qualified Control.Monad.Trans.Lift.Catch as Lift
53+import qualified Control.Monad.Trans.Lift.Listen as Lift
54+import qualified Control.Monad.Trans.Lift.Pass as Lift
55+import qualified Control.Monad.Trans.Lift.CallCC as Lift
56+
57+import Control.Monad.Ether.Reader.Class
58+import Control.Monad.Ether.State.Class
59+import Control.Monad.Ether.Except.Class
60+import Control.Monad.Ether.Writer.Class
61+
62+import qualified Control.Monad.Reader as Class
63+import qualified Control.Monad.State as Class
64+import qualified Control.Monad.Except as Class
65+import qualified Control.Monad.Writer as Class
66+
67+-- | Encode type-level information for 'tagAttach'.
68+data K_TagAttach t = TagAttach t
69+
70+-- | Encode type-level information for 'tagReplace'.
71+data K_TagReplace tOld tNew = TagReplace tOld tNew
72+
73+-- | Wrap a monad to change its tags. Under the hood this is
74+-- simply 'Trans.IdentityT', all the work is happening on the type level.
75+newtype DispatchT dp m a = DispatchT (Trans.IdentityT m a)
76+ deriving
77+ ( Generic
78+ , Functor, Applicative, Alternative, Monad, MonadPlus
79+ , MonadFix, MonadTrans, MonadIO, MFunctor, MMonad
80+ , MonadThrow, MonadCatch, MonadMask )
81+
82+type DispatchTagAttachT t = DispatchT (TagAttach t)
83+type DispatchTagReplaceT tOld tNew = DispatchT (TagReplace tOld tNew)
84+
85+-- | Type-restricted 'coerce'.
86+pack :: Trans.IdentityT m a -> DispatchT dp m a
87+pack = coerce
88+
89+-- | Type-restricted 'coerce'.
90+unpack :: DispatchT dp m a -> Trans.IdentityT m a
91+unpack = coerce
92+
93+instance MB.MonadBase b m => MB.MonadBase b (DispatchT dp m) where
94+ liftBase = MB.liftBaseDefault
95+
96+instance MC.MonadTransControl (DispatchT dp) where
97+ type StT (DispatchT dp) a = MC.StT Trans.IdentityT a
98+ liftWith = MC.defaultLiftWith pack unpack
99+ restoreT = MC.defaultRestoreT pack
100+
101+instance MC.MonadBaseControl b m => MC.MonadBaseControl b (DispatchT dp m) where
102+ type StM (DispatchT dp m) a = MC.ComposeSt (DispatchT dp) m a
103+ liftBaseWith = MC.defaultLiftBaseWith
104+ restoreM = MC.defaultRestoreM
105+
106+type instance Lift.StT (DispatchT dp) a = MC.StT (DispatchT dp) a
107+
108+instance Lift.LiftLocal (DispatchT dp) where
109+ liftLocal = Lift.defaultLiftLocal pack unpack
110+
111+instance Lift.LiftCatch (DispatchT dp) where
112+ liftCatch = Lift.defaultLiftCatch pack unpack
113+
114+instance Lift.LiftListen (DispatchT dp) where
115+ liftListen = Lift.defaultLiftListen pack unpack
116+
117+instance Lift.LiftPass (DispatchT dp) where
118+ liftPass = Lift.defaultLiftPass pack unpack
119+
120+instance Lift.LiftCallCC (DispatchT dp) where
121+ liftCallCC = Lift.defaultLiftCallCC pack unpack
122+ liftCallCC' = Lift.defaultLiftCallCC' pack unpack
123+
124+-- | Attach a tag to untagged transformers.
125+tagAttach :: proxy t -> DispatchTagAttachT t m a -> m a
126+tagAttach _ = coerce
127+
128+-- | Replace a tag with another tag.
129+tagReplace
130+ :: proxy tOld
131+ -> proxy tNew
132+ -> DispatchTagReplaceT tOld tNew m a
133+ -> m a
134+tagReplace _ _ = coerce
135+
136+
137+-- TagAttach instances
138+
139+instance MonadReader tag r m
140+ => Class.MonadReader r (DispatchTagAttachT tag m) where
141+ ask = let t = Proxy :: Proxy tag in Lift.lift (ask t)
142+ local = let t = Proxy :: Proxy tag in Lift.liftLocal (ask t) (local t)
143+
144+instance MonadState tag s m
145+ => Class.MonadState s (DispatchTagAttachT tag m) where
146+ get = let t = Proxy :: Proxy tag in Lift.lift (get t)
147+ put = let t = Proxy :: Proxy tag in Lift.lift . put t
148+
149+instance MonadExcept tag e m
150+ => Class.MonadError e (DispatchTagAttachT tag m) where
151+ throwError = let t = Proxy :: Proxy tag in Lift.lift . throw t
152+ catchError = let t = Proxy :: Proxy tag in Lift.liftCatch (catch t)
153+
154+instance MonadWriter tag w m
155+ => Class.MonadWriter w (DispatchTagAttachT tag m) where
156+ writer = let t = Proxy :: Proxy tag in Lift.lift . writer t
157+ tell = let t = Proxy :: Proxy tag in Lift.lift . tell t
158+ listen = let t = Proxy :: Proxy tag in Lift.liftListen (listen t)
159+ pass = let t = Proxy :: Proxy tag in Lift.liftPass (pass t)
160+
161+
162+-- TagReplace instances
163+
164+instance MonadReader tNew r m
165+ => MonadReader tOld r (DispatchTagReplaceT tOld tNew m) where
166+ ask _ = let t = Proxy :: Proxy tNew in Lift.lift (ask t)
167+ local _ = let t = Proxy :: Proxy tNew in Lift.liftLocal (ask t) (local t)
168+
169+instance MonadState tNew s m
170+ => MonadState tOld s (DispatchTagReplaceT tOld tNew m) where
171+ get _ = let t = Proxy :: Proxy tNew in Lift.lift (get t)
172+ put _ = let t = Proxy :: Proxy tNew in Lift.lift . put t
173+
174+instance MonadExcept tNew e m
175+ => MonadExcept tOld e (DispatchTagReplaceT tOld tNew m) where
176+ throw _ = let t = Proxy :: Proxy tNew in Lift.lift . throw t
177+ catch _ = let t = Proxy :: Proxy tNew in Lift.liftCatch (catch t)
178+
179+instance MonadWriter tNew w m
180+ => MonadWriter tOld w (DispatchTagReplaceT tOld tNew m) where
181+ writer _ = let t = Proxy :: Proxy tNew in Lift.lift . writer t
182+ tell _ = let t = Proxy :: Proxy tNew in Lift.lift . tell t
183+ listen _ = let t = Proxy :: Proxy tNew in Lift.liftListen (listen t)
184+ pass _ = let t = Proxy :: Proxy tNew in Lift.liftPass (pass t)
src/Control/Monad/Trans/Ether/Except.hs+2−2
@@ -78,11 +78,11 @@ newtype ExceptT tag e m a = ExceptT (Trans.ExceptT e m a)
7878 , MonadFix, MonadTrans, MonadIO, MFunctor, MMonad
7979 , MonadThrow, MonadCatch )
8080
81−-- | Type-restricted `coerce`.
81+-- | Type-restricted 'coerce'.
8282pack :: Trans.ExceptT e m a -> ExceptT tag e m a
8383pack = coerce
8484
85−-- | Type-restricted `coerce`.
85+-- | Type-restricted 'coerce'.
8686unpack :: ExceptT tag e m a -> Trans.ExceptT e m a
8787unpack = coerce
8888
src/Control/Monad/Trans/Ether/Reader.hs+2−2
@@ -74,11 +74,11 @@ newtype ReaderT tag r m a = ReaderT (Trans.ReaderT r m a)
7474 , MonadFix, MonadTrans, MonadIO, MFunctor, MMonad
7575 , MonadThrow, MonadCatch, MonadMask )
7676
77−-- | Type-restricted `coerce`.
77+-- | Type-restricted 'coerce'.
7878pack :: Trans.ReaderT r m a -> ReaderT tag r m a
7979pack = coerce
8080
81−-- | Type-restricted `coerce`.
81+-- | Type-restricted 'coerce'.
8282unpack :: ReaderT tag r m a -> Trans.ReaderT r m a
8383unpack = coerce
8484
src/Control/Monad/Trans/Ether/State/Lazy.hs+2−2
@@ -78,11 +78,11 @@ newtype StateT tag s m a = StateT (Trans.StateT s m a)
7878 , MonadFix, MonadTrans, MonadIO, MFunctor
7979 , MonadThrow, MonadCatch, MonadMask )
8080
81−-- | Type-restricted `coerce`.
81+-- | Type-restricted 'coerce'.
8282pack :: Trans.StateT s m a -> StateT tag s m a
8383pack = coerce
8484
85−-- | Type-restricted `coerce`.
85+-- | Type-restricted 'coerce'.
8686unpack :: StateT tag s m a -> Trans.StateT s m a
8787unpack = coerce
8888
src/Control/Monad/Trans/Ether/State/Strict.hs+2−2
@@ -78,11 +78,11 @@ newtype StateT tag s m a = StateT (Trans.StateT s m a)
7878 , MonadFix, MonadTrans, MonadIO, MFunctor
7979 , MonadThrow, MonadCatch, MonadMask )
8080
81−-- | Type-restricted `coerce`.
81+-- | Type-restricted 'coerce'.
8282pack :: Trans.StateT s m a -> StateT tag s m a
8383pack = coerce
8484
85−-- | Type-restricted `coerce`.
85+-- | Type-restricted 'coerce'.
8686unpack :: StateT tag s m a -> Trans.StateT s m a
8787unpack = coerce
8888
src/Control/Monad/Trans/Ether/Writer.hs+2−2
@@ -81,11 +81,11 @@ newtype WriterT tag w m a = WriterT (Trans.WriterT w m a)
8181 , MonadFix, MonadTrans, MonadIO, MFunctor, MMonad
8282 , MonadThrow, MonadCatch, MonadMask )
8383
84−-- | Type-restricted `coerce`.
84+-- | Type-restricted 'coerce'.
8585pack :: Trans.WriterT w m a -> WriterT tag w m a
8686pack = coerce
8787
88−-- | Type-restricted `coerce`.
88+-- | Type-restricted 'coerce'.
8989unpack :: WriterT tag w m a -> Trans.WriterT w m a
9090unpack = coerce
9191
stack-ghc-7.8.4.yaml+1
@@ -31,4 +31,5 @@ extra-deps:
3131- transformers-compat-0.4.0.4
3232- transformers-lift-0.1.0.0
3333- unbounded-delays-0.1.0.9
34+- exceptions-0.8.0.2
3435resolver: ghc-7.8.4
test/Regression.hs+11−56
@@ -1,18 +1,7 @@
1−{-# LANGUAGE TypeFamilies #-}
2−{-# LANGUAGE FlexibleContexts #-}
3−{-# LANGUAGE EmptyDataDecls #-}
4−{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE ConstraintKinds #-}
6−{-# LANGUAGE ScopedTypeVariables #-}
7−{-# LANGUAGE DataKinds #-}
8−{-# LANGUAGE TypeOperators #-}
9−{-# LANGUAGE LambdaCase #-}
101module Main where
112
123import Data.Monoid
134import Control.Monad
14−import Control.Ether.TH
15−import Control.Ether.Wrapped
165
176import Control.Monad.Ether
187import Control.Ether.Abbr
@@ -25,8 +14,9 @@ import qualified Control.Monad.Writer as T
2514import qualified Control.Monad.State as T
2615
2716import Test.Tasty
28−import Test.Tasty.QuickCheck
29−import Test.QuickCheck.Function
17+
18+import Regression.T1
19+import Regression.T2
3020
3121ethereal "R1" "r1"
3222ethereal "R2" "r2"
@@ -39,45 +29,10 @@ main = defaultMain suite
3929
4030suite :: TestTree
4131suite = testGroup "Ether"
42− [ testGroup "ReaderT"
43− [ testProperty "layered sum (local left)" layeredLocalLeft
44− , testProperty "layered sum (local right)" layeredLocalRight
45− ]
32+ [ test1
33+ , test2
4634 ]
4735
48−layeredLocalLeft, layeredLocalRight
49− :: Fun (Int, Integer) Integer
50− -> Fun Integer Integer
51− -> Int -> Integer -> Property
52−
53−layeredLocalLeft k f a1 a2 = property (direct == run indirect)
54− where
55− run = flip (runReader r1) a1 . flip (runReaderT r2) a2
56− (direct, indirect) = layeredLocalCore' k f a1 a2
57−
58−layeredLocalRight k f a1 a2 = property (direct == run indirect)
59− where
60− run = flip (runReader r2) a2 . flip (runReaderT r1) a1
61− (direct, indirect) = layeredLocalCore' k f a1 a2
62−
63−layeredLocalCore
64− :: Ether '[R1 --> r1, R2 --> r2] m
65− => (r2 -> r2) -> (r1 -> r2 -> a) -> m a
66−layeredLocalCore f g = do
67− n <- ask r1
68− m <- local r2 f (ask r2)
69− return (g n m)
70−
71−layeredLocalCore'
72− :: Ether '[R1 --> Int, R2 --> Integer] m
73− => Fun (Int, Integer) Integer
74− -> Fun Integer Integer
75− -> Int -> Integer -> (Integer, m Integer)
76−layeredLocalCore' k f a1 a2 = (direct, indirect)
77− where
78− direct = apply k (fromIntegral a1, apply f a2)
79− indirect = layeredLocalCore (apply f) (\n m -> apply k (fromIntegral n, m))
80−
8136implicitCore :: Ether '[I.R Int, I.R Bool] m => m String
8237implicitCore = I.local (succ :: Int -> Int) $ do
8338 n :: Int <- I.ask
@@ -93,7 +48,7 @@ wrapCore = do
9348
9449wrapCore' :: Ether '[S1 --> Int, S1 <-> Int, R1 --> Int] m => m Int
9550wrapCore' = do
96− a <- ethered s1 wrapCore
51+ a <- tagAttach s1 wrapCore
9752 c <- ask r1
9853 return (a + c)
9954
@@ -186,8 +141,8 @@ wrapState_g = liftM show T.get
186141
187142wrapState_useboth :: Ether '[Foo <-> Int, Bar <-> Bool] m => m String
188143wrapState_useboth = do
189− a <- ethered foo wrapState_f
190− b <- ethered bar wrapState_g
144+ a <- tagAttach foo wrapState_f
145+ b <- tagAttach bar wrapState_g
191146 return (a ++ b)
192147
193148wrapStateCore :: Int -> Bool -> String
@@ -199,7 +154,7 @@ wrapStateBad1_g = modify foo (*100)
199154wrapStateBad1_useboth :: MonadState Foo Int m => m String
200155wrapStateBad1_useboth = do
201156 wrapStateBad1_g
202− ethered foo wrapState_f
157+ tagAttach foo wrapState_f
203158
204159wrapStateBad1 :: Int -> String
205160wrapStateBad1 = evalState foo wrapStateBad1_useboth
@@ -210,7 +165,7 @@ wrapStateBad2 = do
210165 T.get
211166
212167wrapStateBad2Core :: Int -> Int
213−wrapStateBad2Core = evalState foo (ethered foo wrapStateBad2)
168+wrapStateBad2Core = evalState foo (tagAttach foo wrapStateBad2)
214169
215170wrapReaderCore :: Int -> Int
216−wrapReaderCore = runReader foo (ethered foo (liftM2 (+) T.ask (ask foo)))
171+wrapReaderCore = runReader foo (tagAttach foo (liftM2 (+) T.ask (ask foo)))
test/Regression/T1.hsnew file+39
@@ -0,0 +1,39 @@
1+module Regression.T1 (test1) where
2+
3+import Control.Monad.Ether
4+import Control.Ether.Abbr
5+
6+import Test.Tasty
7+import Test.Tasty.QuickCheck
8+
9+ethereal "Tag1" "tag1"
10+ethereal "Tag2" "tag2"
11+
12+testEther
13+ :: Ether '[Tag1 --> String, Tag2 --> String] m
14+ => m ((String, String), (String, String))
15+testEther = do
16+ s1 <- ask tag1
17+ s2 <- ask tag2
18+ let s1s2 = (s1, s2)
19+ s1s2' <- local tag2 (map succ) $ do
20+ s1' <- ask tag1
21+ s2' <- ask tag2
22+ return (s1', s2')
23+ return (s1s2, s1s2')
24+
25+runner1 s1 s2 = flip (runReader tag1) s1 . flip (runReaderT tag2) s2
26+runner2 s1 s2 = flip (runReader tag2) s2 . flip (runReaderT tag1) s1
27+
28+test1 :: TestTree
29+test1 = testGroup "T1: Reader.local"
30+ [ testProperty "runner1 works"
31+ $ \s1 s2 -> property
32+ $ runner1 s1 s2 testEther == ((s1, s2), (s1, map succ s2))
33+ , testProperty "runner1 works"
34+ $ \s1 s2 -> property
35+ $ runner1 s1 s2 testEther == ((s1, s2), (s1, map succ s2))
36+ , testProperty "runner1 == runner2"
37+ $ \s1 s2 -> property
38+ $ runner1 s1 s2 testEther == runner2 s1 s2 testEther
39+ ]
test/Regression/T2.hsnew file+8
@@ -0,0 +1,8 @@
1+module Regression.T2 (test2) where
2+
3+import Test.Tasty
4+
5+test2 :: TestTree
6+test2 = testGroup "T2"
7+ [
8+ ]