Skip to content

Instantly share code, notes, and snippets.

@pkamenarsky
Last active February 24, 2017 10:22
Show Gist options
  • Save pkamenarsky/35c6c6f1f8b374737dab8511a3d60238 to your computer and use it in GitHub Desktop.
Save pkamenarsky/35c6c6f1f8b374737dab8511a3d60238 to your computer and use it in GitHub Desktop.
Rewind monad
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE StandaloneDeriving #-}
module Rs where
import Control.Monad.Free
import qualified Data.Map as M
data RsF m next = ∀ a. RsCheckpoint Int (m a) (a next) | RsRewind Int
deriving instance Functor (RsF m)
type Rs m = Free (RsF m)
checkpoint Int m a Rs m a
checkpoint ch m = liftF (RsCheckpoint ch m id)
rewind Int Rs m a
rewind ch = liftF (RsRewind ch)
runRs Monad m M.Map Int (Rs m a) Rs m a m a
runRs m (Pure a) = return a
runRs m cnt@(Free (RsCheckpoint ch action next)) = do
a action
runRs (M.insert ch cnt m) (next a)
runRs m (Free (RsRewind ch)) = do
case M.lookup ch m of
Just cnt runRs m cnt
Nothing error "Invalid checkpoint"
example IO
example = runRs M.empty $ do
checkpoint 1 $ putStrLn "Enter command: "
a checkpoint 2 $ getLine
if a "rewind"
then rewind 1
else checkpoint 3 $ putStrLn "Bye"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment