packages feed

free-theorems-0.2: src/FrontendOtherTests.hs


module FrontendOtherTests (tests) where



import Control.Monad (liftM)
import Control.Monad.Writer (runWriter)
import Data.Generics (gcount, mkQ)
import Data.Maybe (mapMaybe)
import Data.Set as Set (isSubsetOf)
import Test.QuickCheck 

import Tests

import Language.Haskell.FreeTheorems.Syntax
import Language.Haskell.FreeTheorems.ValidSyntax
import Language.Haskell.FreeTheorems.Frontend as FT
import Language.Haskell.FreeTheorems.Frontend.TypeExpressions
import Language.Haskell.FreeTheorems.Frontend.CheckLocal
import Language.Haskell.FreeTheorems.Frontend.CheckGlobal



-- | Runs all tests.

tests :: IO ()
tests = do
  doTest "replaceTypeSynonyms is complete" prop_replaceTypeSynonymsIsComplete
  doTest "check is stable" prop_checkIsStable






-- | Property: Replacing every type synonym in a type expression does not leave
--   any type synonym.

prop_replaceTypeSynonymsIsComplete ds = 
  withTypeDecls ds $ \ts ->
    let ds' = getDeclarations ds
    in countTypeConSyn ts (replaceAllTypeSynonyms ts ds') == 0

countTypeConSyn ts = gcount (False `mkQ` select)
  where 
    select con = case con of
      Con c     -> c `elem` map typeName ts
      otherwise -> False



-- | Checks a list of declarations and filters all type declarations which then
--   are fed to a property.

withTypeDecls :: ListOfDeclarations -> ([TypeDeclaration] -> Bool) -> Property
withTypeDecls ds prop =
  let getTypeSyn d = case d of { TypeDecl d -> Just d ; otherwise -> Nothing }
      process ds = fst . runWriter $ checkLocal ds >>= checkGlobal []
      typeSyns = mapMaybe getTypeSyn . process . getDeclarations $ ds
   in trivial (null typeSyns) $ prop typeSyns




-- | Property: Checks that applying 'check' twice does not more that applying
--   'check once.

prop_checkIsStable ds = 
  let once  ds = FT.check ds
      twice ds = FT.check . map rawDeclaration =<< FT.check ds
      count f = length . fst . runWriter . f . getDeclarations $ ds
   in count once == count twice