-
Notifications
You must be signed in to change notification settings - Fork 2
/
state.hs
70 lines (52 loc) · 1.62 KB
/
state.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
-- credit: https://gist.github.com/sdiehl/8d991a718f7a9c80f54b
-------------------------------------------------------------------------------
-- State Monad Implementation
-------------------------------------------------------------------------------
newtype State s a = State { runState :: s -> (a,s) }
instance Functor (State s) where
fmap fn (State sa) = State (\s0 -> let (a, s1) = sa s0 in (fn a, s1))
instance Applicative (State s) where
pure a = State (\s -> (a, s))
(State sf) <*> (State sa) =
State (\s0 -> let (fn,s1) = sf s0
(a, s2) = sa s1
in (fn a, s2))
instance Monad (State s) where
return a = pure a
State act >>= k = State (\s ->
let (a, s') = act s
in runState (k a) s')
get :: State s s
get = State $ \s -> (s, s)
put :: s -> State s ()
put s = State $ \_ -> ((), s)
modify :: (s -> s) -> State s ()
modify f = get >>= \x -> put (f x)
evalState :: State s a -> s -> a
evalState act = fst . runState act
execState :: State s a -> s -> s
execState act = snd . runState act
-------------------------------------------------------------------------------
-- Example
-------------------------------------------------------------------------------
type Stack = [Int]
empty :: Stack
empty = []
pop :: State Stack Int
pop = State $ \(x:xs) -> (x,xs)
push :: Int -> State Stack ()
push a = State $ \xs -> ((),a:xs)
tos :: State Stack Int
tos = State $ \(x:xs) -> (x,x:xs)
stackManip :: State Stack Int
stackManip = do
push 10
push 20
a <- pop
b <- pop
push (a+b)
tos
main :: IO ()
main = do
let res = evalState stackManip empty
print res