numerals-base-0.3: src/Text/Numeral/Exp.hs
{-# LANGUAGE NoImplicitPrelude
, PackageImports
, UnicodeSyntax
#-}
module Text.Numeral.Exp
( Exp(..)
, eval
, Side(L, R)
) where
-------------------------------------------------------------------------------
-- Imports
-------------------------------------------------------------------------------
import "base" Data.Bool ( Bool(False, True) )
import "base" Data.Eq ( Eq )
import "base" Data.Ord ( Ord )
import "base" Text.Show ( Show )
import "base-unicode-symbols" Prelude.Unicode ( ℤ )
import qualified "this" Text.Numeral.Exp.Classes as C
-------------------------------------------------------------------------------
-- Exp datatype
-------------------------------------------------------------------------------
-- | An expression that represents the structure of a numeral.
data Exp -- | An unknown value.
= Unknown
-- | A literal value.
| Lit ℤ
-- | Negation of an expression.
| Neg Exp
-- | Addition of two expressions.
| Add Exp Exp
-- | Multiplication of two expressions.
| Mul Exp Exp
-- | One expression subtracted from another expression.
| Sub Exp Exp
-- | A step in a scale of large values.
| Scale ℤ ℤ Exp
deriving (Eq, Ord, Show)
infixl 6 `Add`
infixl 6 `Sub`
infixl 7 `Mul`
-- | Precisely the 'Unknown' constructor.
instance C.Unknown Exp where
unknown = Unknown
isUnknown Unknown = True
isUnknown _ = False
-- | Precisely the 'Lit' constructor.
instance C.Lit Exp where lit = Lit
-- | Precisely the 'Neg' constructor.
instance C.Neg Exp where neg = Neg
-- | Precisely the 'Add' constructor.
instance C.Add Exp where add = Add
-- | Precisely the 'Mul' constructor.
instance C.Mul Exp where mul = Mul
-- | Precisely the 'Sub' constructor.
instance C.Sub Exp where sub = Sub
-- | Precisely the 'Scale' constructor.
instance C.Scale Exp where scale = Scale
-- | Evaluates an expression to a value.
--
-- Law: @e == eval e@
eval ∷ (C.Unknown α, C.Lit α, C.Neg α, C.Add α, C.Mul α, C.Sub α, C.Scale α) ⇒ Exp → α
eval (Add x y) = C.add (eval x) (eval y)
eval (Mul x y) = C.mul (eval x) (eval y)
eval (Sub x y) = C.sub (eval x) (eval y)
eval (Neg x) = C.neg (eval x)
eval (Lit x) = C.lit x
eval (Scale b o r) = C.scale b o (eval r)
eval Unknown = C.unknown
-- prop_eval ∷ Exp → Bool
-- prop_eval e = e ≡ eval e
-------------------------------------------------------------------------------
-- Side
-------------------------------------------------------------------------------
-- | A side or direction, either 'L'eft or 'R'ight.
data Side = L -- ^ Left.
| R -- ^ Right.
deriving Show