Annotations-0.2.1: tests/F/Expr.hs
module F.Expr where
import Annotations.Bounds
import Annotations.F.Annotated
import Annotations.F.Fixpoints
import Control.Applicative (Applicative(..), (<$>))
import Data.Foldable (Foldable(..))
import Data.Traversable
-- type PositionalExpr = (Bounds, PositionalExpr')
-- data PositionalExpr'
-- = Add PositionalExpr PositionalExpr
-- | Sub PositionalExpr PositionalExpr
-- | Mul PositionalExpr PositionalExpr
-- | Div PositionalExpr PositionalExpr
-- | Num Int
data ExprF rT
= Add rT rT
| Sub rT rT
| Mul rT rT
| Div rT rT
| Num Int
deriving (Eq, Show)
instance Functor ExprF where
fmap = fmapDefault
instance Foldable ExprF where
foldMap = foldMapDefault
instance Traversable ExprF where
traverse f expr = case expr of
Add x y -> Add <$> f x <*> f y
Sub x y -> Sub <$> f x <*> f y
Mul x y -> Mul <$> f x <*> f y
Div x y -> Div <$> f x <*> f y
Num n -> pure (Num n)
-- newtype Expr = Expr (ExprF Expr)
-- data PositionalExpr = PositionalExpr Bounds (ExprF PositionalExpr)
newtype Expr = Expr { runExpr :: Fix ExprF }
deriving (Eq, Show)
instance Num Expr where
fromInteger = Expr . In . Num . fromIntegral
Expr x + Expr y = Expr $ In $ Add x y
Expr x - Expr y = Expr $ In $ Sub x y
Expr x * Expr y = Expr $ In $ Mul x y
negate = (0 -)
abs = error "abs"
signum = error "signum"
instance Fractional Expr where
Expr x / Expr y = Expr $ In $ Div x y
fromRational = error "fromRational"
type PositionalExpr = Fix (Ann Bounds ExprF)
cataExpr :: (ExprF a -> a) -> Fix ExprF -> a
cataExpr f (In expr) = f (fmap (cataExpr f) expr)
data ExprAlg a = ExprAlg
{ cataNum :: Int -> a
, cataAdd :: a -> a -> a
, cataSub :: a -> a -> a
, cataMul :: a -> a -> a
, cataDiv :: a -> a -> a
}
cataExpr0 :: ExprAlg a -> Fix ExprF -> a
cataExpr0 alg = f where
f (In expr) = case expr of
Num n -> cataNum alg n
Add x y -> cataAdd alg (f x) (f y)
Sub x y -> cataSub alg (f x) (f y)
Mul x y -> cataMul alg (f x) (f y)
Div x y -> cataDiv alg (f x) (f y)
exprEval :: Algebra ExprF Int
exprEval expr = case expr of
Num n -> n
Add x y -> x + y
Sub x y -> x - y
Mul x y -> x * y
Div x y -> x `div` y
exprEval' :: Algebra (Ann Bounds ExprF)
(Either (Bounds, String) Int)
exprEval' (Ann z expr) = case expr of
Num n -> Right n
Add x y -> (+) <$> x <*> y
Sub x y -> (-) <$> x <*> y
Mul x y -> (*) <$> x <*> y
Div x y -> do
x' <- x
y' <- y
if y' == 0
then Left (z, "division by zero")
else Right (x' `div` y')
exprEvalE :: ErrorAlgebra ExprF String Int
exprEvalE expr = case expr of
Num n -> Right n
Add x y -> Right (x + y)
Sub x y -> Right (x - y)
Mul x y -> Right (x * y)
Div x y
| y == 0 -> Left "division by zero"
| otherwise -> Right (x `div` y)