packages feed

ideas-statistics-1.0: src/Domain/Statistics/ComponentSet.hs

-----------------------------------------------------------------------------
-- Copyright 2020, Ideas project team. This file is distributed under the
-- terms of the Apache License 2.0. For more information, see the files
-- "LICENSE.txt" and "NOTICE.txt", which are included in the distribution.
-----------------------------------------------------------------------------
module Domain.Statistics.ComponentSet
  ( -- * Types
    ComponentSet, module Domain.Statistics.Component
    -- * Constructors
  , initialSet, derivedSet
    -- * Combining and transforming
  , append, delete, mapComponent, initials, derived, toList
   -- * Getters
  , get, getData, getExpr, getRelation, getRhsExpr
  , getTestType, getSided, getRejectionHypotheses, getConclusion
    -- * Membership
  , contains, doesNotContain
  , isInitial, isDerived
  ) where

import Control.Monad
import Data.List hiding (delete)
import Data.Maybe
import Domain.Statistics.Symbols
import Domain.Math.Data.Relation
import Domain.Math.Expr
import Domain.Statistics.Data
import Domain.Statistics.Component
import Ideas.Common.Rewriting hiding (trueSymbol,falseSymbol)
import Ideas.Common.Classes

------------------------------------------------------------------------------
-- Types

data ComponentSet = CS 
   { initialsList :: [(ComponentId, Component)]
   , derivedList  :: [(ComponentId, Component)]
   }

instance Show ComponentSet where
   show cs = unlines (map (f True) (initialsList cs) ++ map (f False) (derivedList cs))
    where
      f b (k, v) =  bracketsIf b (getCId k) ++ ": " ++ show v ++ ";"

      bracketsIf True  s = "[" ++ s ++ "]"
      bracketsIf False s = s

instance Eq ComponentSet where
   CS xs1 xs2 == CS ys1 ys2 = f xs1 == f ys1 && f xs2 == f ys2
    where
      f = sortBy (\(x, _) (y, _) -> x `compare` y)

instance Semigroup ComponentSet where
   CS xs1 xs2 <> CS ys1 ys2 = CS (xs1 ++ ys1) (xs2 ++ ys2)

instance Monoid ComponentSet where
   mempty  = CS [] []
   mappend = (<>)

instance IsTerm ComponentSet where
   toTerm cs = TList $ 
      [ ternary componentSymbol (toTerm k) (symbol initialSymbol) (toTerm c) 
      | (k, c) <- initialsList cs
      ] ++
      [ ternary componentSymbol (toTerm k) (symbol derivedSymbol) (toTerm c) 
      | (k, c) <- derivedList cs
      ]

   fromTerm (TList xs) =
      let f (TCon s [t1, TCon sv [], t3]) | s == componentSymbol = do
             k  <- fromTerm t1
             c  <- fromTerm t3
             if sv == initialSymbol 
                then return $ CS [(k, c)] []
                else if sv == derivedSymbol 
                then return $ CS [] [(k, c)]
                else fail "expected initial/derived"
          f _ = fail "Term is not a component"
      in mconcat <$> mapM f xs
   fromTerm _ = fail "Term is not a component (not a list)"

------------------------------------------------------------------------------
-- Constructors

initialSet :: [(ComponentId, Component)] -> ComponentSet
initialSet xs = CS xs []

derivedSet :: [(ComponentId, Component)] -> ComponentSet
derivedSet = CS []

------------------------------------------------------------------------------
-- Combining and transforming

append :: ComponentId -> Component -> ComponentSet -> ComponentSet
append k v cs = cs <> derivedSet [(k, v)]

delete :: ComponentId -> ComponentSet -> ComponentSet
delete k (CS xs ys) = CS (f xs) (f ys)
 where
   f = filter ((/= k) . fst)

mapComponent :: (Component -> Component) -> ComponentSet -> ComponentSet
mapComponent f (CS xs ys) = CS (change xs) (change ys)
 where
   change = map (mapSecond f)
   
initials :: ComponentSet -> ComponentSet
initials cs = mempty { initialsList = initialsList cs }

derived :: ComponentSet -> ComponentSet 
derived cs = mempty { derivedList = derivedList cs }

toList :: ComponentSet -> [(ComponentId, Component)]
toList cs = initialsList cs ++ derivedList cs

------------------------------------------------------------------------------
-- Getters

get :: Monad m => ComponentId -> ComponentSet -> m Component
get n cs = 
   -- first consider derived components
   case lookup n (derivedList cs ++ initialsList cs) of
      Just c  -> return c
      Nothing -> fail $ show n ++ " missing"

getData :: Monad m => ComponentId -> ComponentSet -> m Data
getData n = get n >=> isData

getExpr :: Monad m => ComponentId -> ComponentSet -> m Expr
getExpr n = get n >=> isExpr

getRelation :: Monad m => ComponentId -> ComponentSet -> m (Relation Expr)
getRelation n = get n >=> isRelation

getRhsExpr :: MonadPlus m => ComponentId -> ComponentSet -> m Expr
getRhsExpr n cs = fmap rightHandSide (getRelation n cs) `mplus` getExpr n cs

getTestType :: Monad m => ComponentId -> ComponentSet -> m TestType
getTestType n = get n >=> isTestType

getSided :: Monad m => ComponentId -> ComponentSet -> m Sided
getSided n = get n >=> isSided

getConclusion :: Monad m => ComponentId -> ComponentSet -> m Bool
getConclusion n = get n >=> isConclusion

getRejectionHypotheses :: Monad m => ComponentId -> ComponentSet -> m RejectionHypotheses
getRejectionHypotheses n = get n >=> isRejectionHypotheses

------------------------------------------------------------------------------
-- Membership

contains :: ComponentSet -> ComponentId -> Bool
contains cs x = isJust (get x cs)

doesNotContain :: ComponentSet -> ComponentId -> Bool
doesNotContain cs = not . contains cs

isInitial :: ComponentId -> ComponentSet -> Bool
isInitial n cs = initials cs `contains` n

isDerived :: ComponentId -> ComponentSet -> Bool
isDerived n cs = derived cs `contains` n