Skip to content

Instantly share code, notes, and snippets.

@TikhonJelvis
Created March 31, 2015 01:14
Show Gist options
  • Save TikhonJelvis/0eebde0ac267e076bf28 to your computer and use it in GitHub Desktop.
Save TikhonJelvis/0eebde0ac267e076bf28 to your computer and use it in GitHub Desktop.
An implementation of the reverse state monad with the extra newtype wrapping and unwrapping needed to actually make it work:
newtype RState s a = RState (s -> (a, s))
-- takes initial state s and outputs both a result and a new state
runRState :: RState s a -> s -> (a, s)
runRState (RState f) start = f start
instance Monad (RState s) where
return x = RState $ \ s -> (x, s)
RState step1 >>= step2 = RState $ \ start ->
let (resultA, final) = step1 intermediate
(resultB, intermediate) = runRState (step2 resultA) start in
(resultB, final)
get = RState $ \ s -> (s, s)
put s' = RState $ \ _ -> ((), s')
nats = do ns <- get
put (0 : map (+ 1) ns)
return ns
@TikhonJelvis
Copy link
Author

Idiomatically, I would actually implement runRState using record syntax:

newtype RState s a = RState { runRState :: a -> (a, s) }

but it's confusing if you're never seen the pattern before.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment