packages feed

fixplate-0.1.7: tests/TestSuite/Attributes.hs

-- | Tests for attributes

module TestSuite.Attributes where

--------------------------------------------------------------------------------

import Test.Tasty
import Test.Tasty.QuickCheck
import Test.QuickCheck

import Control.Applicative
import Control.Monad hiding ( mapM , mapM_ , forM , forM_ )
import Data.List ( sort , intercalate )
import Data.Char ( ord )
import Data.Foldable
import Data.Traversable
import Prelude hiding (foldl,foldr,mapM,mapM_,concat,concatMap)

import Data.Generics.Fixplate.Base
-- import Data.Generics.Fixplate.Misc
import Data.Generics.Fixplate.Attributes
import Data.Generics.Fixplate.Morphisms
import Data.Generics.Fixplate.Traversals

import TestSuite.Tools
import TestSuite.Misc

--------------------------------------------------------------------------------

testgroup_Attributes :: TestTree
testgroup_Attributes = testGroup "Attributes"
  [ testProperty "synthAccumL"            prop_synthAccumL
  , testProperty "synthAccumR"            prop_synthAccumR
  , testProperty "synthetise"             prop_synthetise
  , testProperty "synthCata"              prop_synthCata
  , testProperty "synthPara"              prop_synthPara
  , testProperty "synthPara'"             prop_synthPara'
  , testProperty "scanCata"               prop_scanCata 
  , testProperty "mapAccumCata"           prop_mapAccumCata
  , testProperty "zygo"                   prop_zygo
  , testProperty "zygo_"                  prop_zygo_
  ]

--------------------------------------------------------------------------------

{-
runtests_Attributes :: IO ()
runtests_Attributes = do
  quickCheck prop_synthAccumL
  quickCheck prop_synthAccumR
  quickCheck prop_synthetise
  quickCheck prop_synthCata
  quickCheck prop_synthPara
  quickCheck prop_synthPara'
  quickCheck prop_scanCata 
  quickCheck prop_mapAccumCata
  quickCheck prop_zygo
  quickCheck prop_zygo_
-}

prop_synthAccumL :: FixT Label -> Bool
prop_synthAccumL tree = 
  toList (Attrib (synthAccumL_ (\i _ -> (i+1,i)) 1 tree)) == [1..length (universe tree)]

prop_synthAccumR :: FixT Label -> Bool
prop_synthAccumR tree = 
  toList (Attrib (synthAccumR_ (\i _ -> (i+1,i)) 1 tree)) == reverse [1..length (universe tree)]

prop_synthetise :: FixT Label -> Bool
prop_synthetise tree = 
  map attribute (universe $ synthetise (\(TreeF (Label l) xs) -> l ++ concat xs) tree)
  ==
  map fold (universe tree)
  where
    fold = foldLeft (\s (Fix (TreeF (Label l) _)) -> s++l) []

prop_synthCata :: FixT Label -> Bool
prop_synthCata tree = attribute (synthCata f tree) == cata f tree where 
  f :: TreeF Label String -> String
  f (TreeF (Label label) xs) = label++"(" ++ intercalate "," xs ++ ")"

prop_synthPara' :: FixT Label -> Bool
prop_synthPara' tree = attribute (synthPara' h tree) == para' h tree where 
  h :: FixT Label -> TreeF Label String -> String
  h tree@(Fix (TreeF label ts)) ys = unLabel label++"_"++show siz++"(" ++ intercalate "," (zipWith c (toList ys) sizs) ++ ")" where
    siz = cata f tree
    sizs = map (cata f) ts
    f t = (1::Int) + Data.Foldable.sum t
    c str j = str ++ "<" ++ show j ++ ">"

prop_synthPara :: FixT Label -> Bool
prop_synthPara tree = attribute (synthPara g tree) == para g tree where 
  g :: TreeF Label (FixT Label , String) -> String
  g (TreeF (Label label) xs) = label++"(" ++ intercalate "," (map u xs) ++ ")" where
    u (tree,a) = show siz ++ "_" ++ a where
      siz = cata (\t -> (1::Int) + Data.Foldable.sum t) tree

scanCataNaive :: Functor f => (a -> f b -> b) -> Attr f a -> Attr f b
scanCataNaive f = annZipWith (flip const) . synthCata (\(Ann a x) -> f a x)

prop_scanCata :: Attr (TreeF Label) String -> Bool
prop_scanCata tree = scanCata f tree == scanCataNaive f tree where
  f :: (String -> TreeF Label Integer -> Integer) -- -> Attr (TreeF Label) String -> Attr (TreeF Label) Integer
  f str t = Prelude.product (toList t) + sumchar str
  sumchar :: String -> Integer
  sumchar = fromIntegral . Prelude.sum . map ord 
--   tree = synthetise (\(TreeF (Label l) xs) -> map toUpper l ++ concat xs) tree) tree0

mapAccumCataNaive :: Functor f => (f acc -> b -> (acc,c)) -> Attr f b -> (acc, Attr f c)
mapAccumCataNaive f = second (annZipWith (flip const)) . synthAccumCata (\(Ann b t) -> f t b)

prop_mapAccumCata :: Attr (TreeF Label) String -> Bool
prop_mapAccumCata tree = mapAccumCata f tree == mapAccumCataNaive f tree where
  f :: (TreeF Label Integer -> String -> (Integer,String)) -- -> Attr (TreeF Label) String -> Attr (TreeF Label) Integer
  f t str = ( k - fromIntegral (length str) + sumchar str , "<" ++ show k ++ "," ++ str ++ ">") where 
    ls = toList t
    k  = Prelude.product ls
  sumchar :: String -> Integer
  sumchar = fromIntegral . Prelude.sum . map ord 
  -- tree = synthetise (\(TreeF (Label l) xs) -> map toLower l ++ concat xs) tree) tree0

--------------------------------------------------------------------------------
-- Morphism tests which are here to avoid circular imports

zygoNaive_ :: Functor f => (f b -> b) -> (f (b,a) -> a) -> Mu f -> a
zygoNaive_ g h = para (h . fmap (first attribute) . unAnn) . synthCata g 

zygoNaive :: Functor f => (f b -> b) -> (f (b,a) -> a) -> Mu f -> (b,a)
zygoNaive g h tree = (attribute tmp, para h1 tmp) where 
  tmp = synthCata g tree
  h1 = h . fmap (first attribute) . unAnn

prop_zygo :: FixT Label -> Bool
prop_zygo tree = zygo g h tree == zygoNaive g h tree where
  g :: TreeF Label Integer -> Integer
  g (TreeF (Label label) child) = Prelude.product child + sumchar label

  h :: TreeF Label (Integer,String) -> String
  h (TreeF (Label label) child) = "[" ++ label ++ "]<" ++ intercalate "," (map f child) ++ ">"

  f (k,s) = show k ++ "_" ++ s

  sumchar = fromIntegral . Prelude.sum . map ord 

prop_zygo_ :: FixT Label -> Bool
prop_zygo_ tree = zygo_ g h tree == zygoNaive_ g h tree where
  g :: TreeF Label Integer -> Integer
  g (TreeF (Label label) child) = Prelude.product child + prodchar label

  h :: TreeF Label (Integer,String) -> String
  h (TreeF (Label label) child) = "<" ++ intercalate "," (map f child) ++ ">" ++ "[" ++ label ++ "]"

  f (k,s) = s ++ "_" ++ show k

  prodchar = fromIntegral . Prelude.product . map ord 
  
--------------------------------------------------------------------------------