Skip to content

Instantly share code, notes, and snippets.

@beala
Last active August 29, 2015 14:22
Show Gist options
  • Save beala/9e1f553f8fb8d2d061c6 to your computer and use it in GitHub Desktop.
Save beala/9e1f553f8fb8d2d061c6 to your computer and use it in GitHub Desktop.
Using tardis (forwards and backwards state monad) to implement a toy language that lets you dereference a var before assigning to it.
{-# LANGUAGE RecursiveDo #-}
import Control.Monad.Tardis
import qualified Data.Map as M
-- Language that lets you dereference variable names and assign to names,
-- but assignment must happen *after* dereference!
data ReverseLang = Assign String Int -- Assign to a name.
| Var String -- Dereference a name.
-- A program is a list of dereferences and assignments.
type Program = [ReverseLang]
program :: Program
program = [ Var "a" -- Dereference "a"
, Var "b"
, Var "c"
, Assign "c" 3
, Var "a"
, Assign "a" 1 -- Assign to "a"
, Assign "b" 2
]
-- Sum all the dereferenced variables in a program.
sumProg :: Program -> Tardis (M.Map String Int) (Maybe Int) (Maybe Int)
sumProg ((Var s) : vs) = do
acc <- getPast
varMap <- getFuture
sendFuture $ do -- Propogate the accumulated sum forward.
a <- acc
a' <- M.lookup s varMap
return $ a + a'
sumProg vs
sumProg ((Assign n i) : vs) = do
rec -- Propogate the assignments backwards in time.
sendPast (M.insert n i varMap)
varMap <- getFuture
sumProg vs
sumProg [] = getPast
main :: IO ()
main = do
print $ evalTardis (sumProg program) (M.empty, Just 0)
@beala
Copy link
Author

beala commented Jun 5, 2015

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