module Main where

newtype Fix f = In { out :: f (Fix f) }

newtype AnnFix x f = AnnFix { runAnnFix :: (x, f (AnnFix x f)) }

data ExpF r
  = Num Integer
  | Add r r
  | Mul r r
  | If r r r

type BareExp = Fix ExpF

eval :: BareExp -> Integer
eval (In (Num i)) = i
eval (In (Add x y)) = eval x + eval y
eval (In (Mul x y)) = eval x * eval y
eval (In (If t x y)) | eval t == 0 = eval y
                     | otherwise = eval x

e = In (Add (In (Num 7)) (In (Num 8)))

type Pos = Int

type PosExp = AnnFix Pos ExpF

aEval (AnnFix (_, e)) =
  case e of
    Num i -> i
    Add x y -> aEval x + aEval y
    Mul x y -> aEval x * aEval y
    If t x y | aEval t == 0 -> aEval y
             | otherwise -> aEval x

ae = AnnFix (3, Add (AnnFix (1, Num 7)) (AnnFix (5, Num 8)))

main = do print (eval e)
          print (aEval ae)
