packages feed

exchangealgebra-0.6.0.0: test/compat-clients/CompatInstance.hs

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}

module CompatInstance (checkInstances) where

import Control.Monad (unless)
import Data.Hashable (Hashable)
import ExchangeAlgebra.Accounting.Account ( AccountDivision(..)
                                          , AccountTitles(..)
                                          , FixedCurrent(..)
                                          , PIMO(..)
                                          , Side(..)
                                          )
import ExchangeAlgebra.Accounting.Exchange (ExBaseClass(..), Exchange(..))
import ExchangeAlgebra.Algebra (Alg, Redundant(..), (.@))
import ExchangeAlgebra.Algebra.Base ( BaseClass
                                    , Element(..)
                                    , Hat(..)
                                    , HatBase((:<))
                                    , HatBaseClass(..)
                                    )
import qualified ExchangeAlgebra.Journal as J

newtype DefaultBase = DefaultBase (HatBase AccountTitles)
    deriving (Eq, Ord, Show, Hashable)

instance Element DefaultBase where
    wildcard = DefaultBase wildcard

instance BaseClass DefaultBase

instance HatBaseClass DefaultBase where
    type BasePart DefaultBase = AccountTitles
    base (DefaultBase wrapped) = base wrapped
    hat (DefaultBase wrapped) = hat wrapped
    merge h title = DefaultBase (h :< title)
    toHat (DefaultBase wrapped) = DefaultBase (toHat wrapped)
    toNot (DefaultBase wrapped) = DefaultBase (toNot wrapped)
    revHat (DefaultBase wrapped) = DefaultBase (revHat wrapped)
    isHat (DefaultBase wrapped) = isHat wrapped
    isNot (DefaultBase wrapped) = isNot wrapped

instance ExBaseClass DefaultBase where
    getAccountTitle (DefaultBase (_ :< title)) = title
    setAccountTitle (DefaultBase (h :< _)) title = DefaultBase (h :< title)

newtype OverrideBase = OverrideBase (HatBase AccountTitles)
    deriving (Eq, Ord, Show, Hashable)

instance Element OverrideBase where
    wildcard = OverrideBase wildcard

instance BaseClass OverrideBase

instance HatBaseClass OverrideBase where
    type BasePart OverrideBase = AccountTitles
    base (OverrideBase wrapped) = base wrapped
    hat (OverrideBase wrapped) = hat wrapped
    merge h title = OverrideBase (h :< title)
    toHat (OverrideBase wrapped) = OverrideBase (toHat wrapped)
    toNot (OverrideBase wrapped) = OverrideBase (toNot wrapped)
    revHat (OverrideBase wrapped) = OverrideBase (revHat wrapped)
    isHat (OverrideBase wrapped) = isHat wrapped
    isNot (OverrideBase wrapped) = isNot wrapped

instance ExBaseClass OverrideBase where
    getAccountTitle (OverrideBase (_ :< title)) = title
    setAccountTitle (OverrideBase (h :< _)) title = OverrideBase (h :< title)
    whatDiv _ = Revenue
    isContra _ = True

check :: (Eq a, Show a) => String -> a -> a -> IO ()
check label expected actual =
    unless (expected == actual) (fail (label ++ ": " ++ show actual))

checkInstances :: IO ()
checkInstances = do
    let debit = DefaultBase (Not :< Cash)
        credit = DefaultBase (Hat :< Cash)
        alg = 4 .@ debit .+ 4 .@ credit :: Alg Double DefaultBase
        journal = alg J..| "tx" :: J.Journal String Double DefaultBase
        debitOnly = 4 .@ debit :: Alg Double DefaultBase
        debitJournal = debitOnly J..| "tx" :: J.Journal String Double DefaultBase
        override = OverrideBase (Not :< Cash)
    check "default division" Assets (whatDiv debit)
    check "default contra" False (isContra debit)
    check "default PIMO" PS (whatPIMO debit)
    check "default current" Current (fixedCurrent debit)
    check "default debit side" Debit (whichSide debit)
    check "default credit side" Credit (whichSide credit)
    check "override division" Revenue (whatDiv override)
    check "override contra" True (isContra override)
    check "override PIMO" OUT (whatPIMO override)
    check "override side" Debit (whichSide override)
    check "Alg decL" 4 (norm (decL alg))
    check "Alg decR" 4 (norm (decR alg))
    check "Alg balance" True (balance alg)
    check "Alg diffRL" (Side, 0) (diffRL alg)
    check "Alg debit-only balance" False (balance debitOnly)
    check "Alg debit-only diffRL" (Debit, 4) (diffRL debitOnly)
    check "Journal decL" 4 (norm (decL journal))
    check "Journal decR" 4 (norm (decR journal))
    check "Journal balance" True (balance journal)
    check "Journal diffRL" (Side, 0) (diffRL journal)
    check "Journal debit-only balance" False (balance debitJournal)
    check "Journal debit-only diffRL" (Debit, 4) (diffRL debitJournal)
    putStrLn "[PASS] user-defined instances and exchange results"