/
Class.hs
152 lines (128 loc) · 4.61 KB
/
Class.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
150
151
152
{-# LANGUAGE UndecidableInstances #-}
-- Search for UndecidableInstances to see why this is needed
-----------------------------------------------------------------------------
-- |
-- Module : Control.Monad.State.Class
-- Copyright : (c) Andy Gill 2001,
-- (c) Oregon Graduate Institute of Science and Technology, 2001
-- License : BSD-style (see the file LICENSE)
--
-- Maintainer : libraries@haskell.org
-- Stability : experimental
-- Portability : non-portable (multi-param classes, functional dependencies)
--
-- MonadState class.
--
-- This module is inspired by the paper
-- /Functional Programming with Overloading and Higher-Order Polymorphism/,
-- Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>)
-- Advanced School of Functional Programming, 1995.
-----------------------------------------------------------------------------
module Control.Monad.State.Class (
MonadState(..),
modify,
gets,
) where
import Control.Monad.Trans.Cont
import Control.Monad.Trans.Error
import Control.Monad.Trans.Identity
import Control.Monad.Trans.List
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.Reader
import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS (RWST, get, put, state)
import qualified Control.Monad.Trans.RWS.Strict as StrictRWS (RWST, get, put, state)
import qualified Control.Monad.Trans.State.Lazy as Lazy (StateT, get, put, state)
import qualified Control.Monad.Trans.State.Strict as Strict (StateT, get, put, state)
import Control.Monad.Trans.Writer.Lazy as Lazy
import Control.Monad.Trans.Writer.Strict as Strict
import Control.Monad.Trans.Class (lift)
import Control.Monad
import Data.Monoid
-- ---------------------------------------------------------------------------
-- | Minimal definition is either both of @get@ and @put@ or just @state@
class Monad m => MonadState s m | m -> s where
-- | Return the state from the internals of the monad.
get :: m s
get = state (\s -> (s, s))
-- | Replace the state inside the monad.
put :: s -> m ()
put s = state (\_ -> ((), s))
-- | Embed a simple state action into the monad.
state :: (s -> (a, s)) -> m a
state f = do
s <- get
let ~(a, s') = f s
put s'
return a
-- | Monadic state transformer.
--
-- Maps an old state to a new state inside a state monad.
-- The old state is thrown away.
--
-- > Main> :t modify ((+1) :: Int -> Int)
-- > modify (...) :: (MonadState Int a) => a ()
--
-- This says that @modify (+1)@ acts over any
-- Monad that is a member of the @MonadState@ class,
-- with an @Int@ state.
modify :: MonadState s m => (s -> s) -> m ()
modify f = state (\s -> ((), f s))
-- | Gets specific component of the state, using a projection function
-- supplied.
gets :: MonadState s m => (s -> a) -> m a
gets f = do
s <- get
return (f s)
instance Monad m => MonadState s (Lazy.StateT s m) where
get = Lazy.get
put = Lazy.put
state = Lazy.state
instance Monad m => MonadState s (Strict.StateT s m) where
get = Strict.get
put = Strict.put
state = Strict.state
instance (Monad m, Monoid w) => MonadState s (LazyRWS.RWST r w s m) where
get = LazyRWS.get
put = LazyRWS.put
state = LazyRWS.state
instance (Monad m, Monoid w) => MonadState s (StrictRWS.RWST r w s m) where
get = StrictRWS.get
put = StrictRWS.put
state = StrictRWS.state
-- ---------------------------------------------------------------------------
-- Instances for other mtl transformers
--
-- All of these instances need UndecidableInstances,
-- because they do not satisfy the coverage condition.
instance MonadState s m => MonadState s (ContT r m) where
get = lift get
put = lift . put
state = lift . state
instance (Error e, MonadState s m) => MonadState s (ErrorT e m) where
get = lift get
put = lift . put
state = lift . state
instance MonadState s m => MonadState s (IdentityT m) where
get = lift get
put = lift . put
state = lift . state
instance MonadState s m => MonadState s (ListT m) where
get = lift get
put = lift . put
state = lift . state
instance MonadState s m => MonadState s (MaybeT m) where
get = lift get
put = lift . put
state = lift . state
instance MonadState s m => MonadState s (ReaderT r m) where
get = lift get
put = lift . put
state = lift . state
instance (Monoid w, MonadState s m) => MonadState s (Lazy.WriterT w m) where
get = lift get
put = lift . put
state = lift . state
instance (Monoid w, MonadState s m) => MonadState s (Strict.WriterT w m) where
get = lift get
put = lift . put
state = lift . state