Skip to content

Instantly share code, notes, and snippets.

@CodeDmitry
Forked from sdiehl/state.hs
Created January 28, 2017 16:28
Show Gist options
  • Select an option

  • Save CodeDmitry/52d1607a015c819823cf002a46658c9d to your computer and use it in GitHub Desktop.

Select an option

Save CodeDmitry/52d1607a015c819823cf002a46658c9d to your computer and use it in GitHub Desktop.

Revisions

  1. @sdiehl sdiehl created this gist Jan 13, 2015.
    61 changes: 61 additions & 0 deletions state.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,61 @@
    import Control.Monad

    -------------------------------------------------------------------------------
    -- State Monad Implementation
    -------------------------------------------------------------------------------

    newtype State s a = State { runState :: s -> (a,s) }

    instance Monad (State s) where
    return a = State $ \s -> (a, s)

    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