{-# LANGUAGE GeneralizedNewtypeDeriving #-}

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