@@ -0,0 +1,146 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE TypeFamilies #-}
3+{-# LANGUAGE FlexibleInstances #-}
4+{-# LANGUAGE FlexibleContexts #-}
5+{-# LANGUAGE UndecidableInstances #-}
6+{-# LANGUAGE DataKinds #-}
7+{-# LANGUAGE ConstraintKinds #-}
8+{-# LANGUAGE TypeOperators #-}
9+{-# LANGUAGE FunctionalDependencies #-}
10+{-# LANGUAGE ScopedTypeVariables #-}
11+{-# LANGUAGE RankNTypes #-}
12+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
13+module Control.Monad.Ether.State
14+ ( EtherStateT
15+ , EtherState
16+ , StateT'
17+ , State'
18+ , runEtherStateT
19+ , runEtherState
20+ , runStateT'
21+ , runState'
22+ --
23+ , MonadEtherState
24+ , etherGet
25+ , etherGets
26+ , etherPut
27+ , etherState
28+ --
29+ , MonadState'
30+ , get'
31+ , gets'
32+ , put'
33+ , state'
34+ ) where
35+
36+import Data.Proxy (Proxy(Proxy))
37+import Control.Monad.Trans (lift)
38+
39+import Control.Monad.Trans.Ether.State
40+
41+-- for mtl instances
42+import qualified Control.Monad.Trans.Cont as Trans (ContT)
43+import qualified Control.Monad.Trans.Except as Trans (ExceptT)
44+import qualified Control.Monad.Trans.Identity as Trans (IdentityT)
45+import qualified Control.Monad.Trans.List as Trans (ListT)
46+import qualified Control.Monad.Trans.Maybe as Trans (MaybeT)
47+import qualified Control.Monad.Trans.Reader as Trans (ReaderT)
48+import qualified Control.Monad.Trans.State.Lazy as Trans.Lazy (StateT)
49+import qualified Control.Monad.Trans.State.Strict as Trans.Strict (StateT)
50+import qualified Control.Monad.Trans.Writer.Lazy as Trans.Lazy (WriterT)
51+import qualified Control.Monad.Trans.Writer.Strict as Trans.Strict (WriterT)
52+
53+class Monad m => MonadEtherState tag s m | m tag -> s where
54+
55+ {-# MINIMAL etherState | etherGet, etherPut #-}
56+
57+ etherGet :: proxy tag -> m s
58+ etherGet proxy = etherState proxy (\s -> (s, s))
59+
60+ etherPut :: proxy tag -> s -> m ()
61+ etherPut proxy s = etherState proxy (\_ -> ((), s))
62+
63+ etherState :: proxy tag -> (s -> (a, s)) -> m a
64+ etherState proxy f = do
65+ s <- etherGet proxy
66+ let ~(a, s') = f s
67+ etherPut proxy s'
68+ return a
69+
70+etherGets :: MonadEtherState tag s m => proxy tag -> (s -> a) -> m a
71+etherGets proxy f = fmap f (etherGet proxy)
72+
73+type MonadState' s = MonadEtherState s s
74+
75+get' :: forall m s . MonadState' s m => m s
76+get' = etherGet (Proxy :: Proxy s)
77+
78+gets' :: forall m s a . MonadState' s m => (s -> a) -> m a
79+gets' = etherGets (Proxy :: Proxy s)
80+
81+put' :: forall m s . MonadState' s m => s -> m ()
82+put' = etherPut (Proxy :: Proxy s)
83+
84+state' :: forall m s a . MonadState' s m => (s -> (a, s)) -> m a
85+state' = etherState (Proxy :: Proxy s)
86+
87+instance {-# OVERLAPPING #-} Monad m => MonadEtherState tag s (EtherStateT tag s m) where
88+ etherGet proxy = etherStateT proxy (\s -> return (s, s))
89+ etherPut proxy s = etherStateT proxy (\_ -> return ((), s))
90+
91+instance (MonadEtherState tag s m) => MonadEtherState tag s (EtherStateT tag' s' m) where
92+ etherGet proxy = lift (etherGet proxy)
93+ etherPut proxy = lift . etherPut proxy
94+ etherState proxy = lift . etherState proxy
95+
96+-- Instances for mtl transformers
97+
98+instance MonadEtherState tag s m => MonadEtherState tag s (Trans.ContT r m) where
99+ etherGet proxy = lift (etherGet proxy)
100+ etherPut proxy = lift . etherPut proxy
101+ etherState proxy = lift . etherState proxy
102+
103+instance MonadEtherState tag s m => MonadEtherState tag s (Trans.ExceptT e m) where
104+ etherGet proxy = lift (etherGet proxy)
105+ etherPut proxy = lift . etherPut proxy
106+ etherState proxy = lift . etherState proxy
107+
108+instance MonadEtherState tag s m => MonadEtherState tag s (Trans.IdentityT m) where
109+ etherGet proxy = lift (etherGet proxy)
110+ etherPut proxy = lift . etherPut proxy
111+ etherState proxy = lift . etherState proxy
112+
113+instance MonadEtherState tag s m => MonadEtherState tag s (Trans.ListT m) where
114+ etherGet proxy = lift (etherGet proxy)
115+ etherPut proxy = lift . etherPut proxy
116+ etherState proxy = lift . etherState proxy
117+
118+instance MonadEtherState tag s m => MonadEtherState tag s (Trans.MaybeT m) where
119+ etherGet proxy = lift (etherGet proxy)
120+ etherPut proxy = lift . etherPut proxy
121+ etherState proxy = lift . etherState proxy
122+
123+instance MonadEtherState tag s m => MonadEtherState tag s (Trans.ReaderT r m) where
124+ etherGet proxy = lift (etherGet proxy)
125+ etherPut proxy = lift . etherPut proxy
126+ etherState proxy = lift . etherState proxy
127+
128+instance MonadEtherState tag s m => MonadEtherState tag s (Trans.Lazy.StateT s' m) where
129+ etherGet proxy = lift (etherGet proxy)
130+ etherPut proxy = lift . etherPut proxy
131+ etherState proxy = lift . etherState proxy
132+
133+instance MonadEtherState tag s m => MonadEtherState tag s (Trans.Strict.StateT s' m) where
134+ etherGet proxy = lift (etherGet proxy)
135+ etherPut proxy = lift . etherPut proxy
136+ etherState proxy = lift . etherState proxy
137+
138+instance (Monoid w, MonadEtherState tag s m) => MonadEtherState tag s (Trans.Lazy.WriterT w m) where
139+ etherGet proxy = lift (etherGet proxy)
140+ etherPut proxy = lift . etherPut proxy
141+ etherState proxy = lift . etherState proxy
142+
143+instance (Monoid w, MonadEtherState tag s m) => MonadEtherState tag s (Trans.Strict.WriterT w m) where
144+ etherGet proxy = lift (etherGet proxy)
145+ etherPut proxy = lift . etherPut proxy
146+ etherState proxy = lift . etherState proxy