packages feed

lambdabot-4.0: Plugin/Lambda/ArithTerm.hs

module Plugin.Lambda.ArithTerm where

import Plugin.Lambda.LangPack

import Data.Dynamic
import Control.Monad.Error

data ArithTerm term
   = Num !Integer
   | Neg term
   | Add term term
   | Sub term term
   | Mul term term
   | Div term term

prjI :: (MonadError String m) => m Dynamic -> m Integer
prjI = prj'

phiArith :: (MonadError String m) => ArithTerm (m Dynamic) -> m Dynamic
phiArith (Num n) = return (inj n)
phiArith (Neg n) = do n' <- prjI n; return $ inj (-n')
phiArith (Add l r) = do l' <- prjI l
                        r' <- prjI r
                        return $ inj (l' + r')
phiArith (Sub l r) = do l' <- prjI l
                        r' <- prjI r
                        return $ inj (l' - r')
phiArith (Mul l r) = do l' <- prjI l
                        r' <- prjI r
                        return $ inj (l' * r')
phiArith (Div l r) = do l' <- prjI l
                        r' <- prjI r
                        if r' == 0 then throwError "divide by zero"
                                   else return $ inj (l' `div` r')

instance Functor ArithTerm where
    fmap _ (Num n) = Num n
    fmap f (Neg n) = Neg (f n)
    fmap f (Add l r) = Add (f l) (f r)
    fmap f (Sub l r) = Sub (f l) (f r)
    fmap f (Mul l r) = Mul (f l) (f r)
    fmap f (Div l r) = Div (f l) (f r)