Skip to content

Instantly share code, notes, and snippets.

@lmarburger
Last active August 29, 2015 14:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lmarburger/8ce711bd1c71e470ce83 to your computer and use it in GitHub Desktop.
Save lmarburger/8ce711bd1c71e470ce83 to your computer and use it in GitHub Desktop.
Extending Idris tutorial 4.4.1 to include a Let operation
data Expr = Var String
| Val Int
| Add Expr Expr
| Let (List (String, Int)) Expr
data Eval : Type -> Type where
MkEval : (List (String, Int) -> Maybe a) -> Eval a
fetch : String -> Eval Int
fetch x = MkEval (\e => fetchVal e) where
fetchVal : List (String, Int) -> Maybe Int
fetchVal [] = Nothing
fetchVal ((v, val) :: xs) = if (x == v)
then (Just val)
else (fetchVal xs)
instance Functor Eval where
map f (MkEval g) = MkEval (\e => map f (g e))
instance Applicative Eval where
pure x = MkEval (\e => Just x)
(<$>) (MkEval f) (MkEval g) = MkEval (\x => app (f x) (g x)) where
app : Maybe (a -> b) -> Maybe a -> Maybe b
app (Just fx) (Just gx) = Just (fx gx)
app _ _ = Nothing
mutual
eval : Expr -> Eval Int
eval (Var x) = fetch x
eval (Val x) = [| x |]
eval (Add x y) = [| eval x + eval y |]
eval (Let newEnv x) = MkEval (\env => runEval (newEnv ++ env) x)
runEval : List (String, Int) -> Expr -> Maybe Int
runEval env e = case eval e of
MkEval envFn => envFn env
*eval> runEval [("A", 2)] (Add (Var "A") (Let [("A", 40)] (Var "A")))
Just 42 : Maybe Int
*eval> runEval [("A", 1)] (Let [("A", 2)] (Let [("A", 3)] (Var "A")))
Just 3 : Maybe Int
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment