summaryrefslogtreecommitdiff
path: root/Haskell-book/26/MaybeT/src/State.hs
blob: d30fdd554ce36d393e2e07d134e7df5dd7820bf0 (plain)
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
module State where

import MonadIO
import MonadTrans

newtype StateT s m a =
    StateT { runStateT :: s -> m (a, s) }

-- 1
instance (Functor m)
      => Functor (StateT s m) where
    fmap f (StateT m) = StateT $ \s -> fmap first $ m s
            where first = uncurry (\t1 t2 -> ((f t1), t2))
            
-- 2
-- Links:
--   http://stackoverflow.com/questions/18673525/is-it-possible-to-implement-applicative-m-applicative-statet-s-m
--   https://github.com/NICTA/course/issues/134
instance (Monad m)
      => Applicative (StateT s m) where
    pure x = StateT $ (\s -> pure (x, s))
    StateT g <*> StateT h = StateT $ \s -> keepFirst <$> g s <*> h s
        where keepFirst (f, s') (x, _) = (f x, s')
  

-- 3
instance (Monad m)
      => Monad (StateT s m) where
    return = pure

    (StateT sma) >>= f =
        StateT $ \s -> do
            a <- sma s
            runStateT (f $ fst a) s

instance MonadTrans (StateT s) where
    lift c = StateT $ \s -> c >>= (\x -> return (x, s))

instance (MonadIO m)
  => MonadIO (StateT s m) where
      liftIO = lift . liftIO