{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-- | Version 0 of the interpreter
module Interpreter0 where

import qualified Control.Monad          as CM
import qualified Control.Monad.Identity as CMI

-- | The simplest expression language imaginable.
data Expr = Lit Integer
          | Expr :+ Expr
  deriving (Show)

type Value = Integer

{- | A monad for evaluating expressions. Just the identity monad
   at this point. Newtyped for abstraction purposes, could just
   as well be @type Eval = Identity@
-}
newtype Eval a = Eval { unEval :: CMI.Identity a }
  deriving (Monad) -- using newtype deriving (Haskell extension)

runEval :: Eval a -> a
runEval = CMI.runIdentity
        . unEval

-- | A monadic evaluator.
eval :: Expr  -> Eval Value
eval (Lit n)   = return n
eval (a :+ b)  = CM.liftM2 (+) (eval a) (eval b)

testExpr = Lit 1700  :+   Lit 38
test = runEval $ eval testExpr