{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Language.Nominal.Properties.NomSpec
where
import Data.Function (on, (&))
import Data.Set as S
import Data.Default
import Data.List.Extra as LE
import Test.QuickCheck
import Language.Nominal.Name
import Language.Nominal.NameSet
import Language.Nominal.Nom
import Language.Nominal.Binder
import Language.Nominal.Properties.SpecUtilities ()
prop_x_neq_x :: Nom [Name Int] -> Property
prop_x_neq_x x = expectFailure $ x == x
prop_split_scope :: Name String -> Bool
prop_split_scope n = unNom $ do
let (x1,x2) = (resN [n] n, resN [n] n)
y1 <- x1
y2 <- x2
return $ y1 /= y2
prop_fresh_neq :: Name () -> Bool
prop_fresh_neq n = unNom $ do
n' <- freshName ()
return $ n /= n'
prop_fresh_neq' :: Bool
prop_fresh_neq' = let x = freshName () in x /= x
prop_fresh_neq'' :: Bool
prop_fresh_neq'' = let x = exit (freshName ()) in x == x
prop_fresh_eq :: Bool
prop_fresh_eq =
let x' = freshName () in
unNom $ do
x <- x'
return $ x == x
prop_freshFor1 :: Name () -> Name () -> Bool
prop_freshFor1 n n' = not $ n `freshFor` (n,n')
prop_freshFor2 :: Name () -> Bool
prop_freshFor2 n = unNom $ do
n' <- freshName ()
return $ n `freshFor` n'
prop_transposeNomMaybe :: Nom (Maybe [Name Int]) -> Bool
prop_transposeNomMaybe x' = unNom $ do
l1' <- x'
l2' <- transposeFM (transposeMF x')
return $ ((==) `on` fmap (fmap nameLabel)) l1' l2'
prop_transposeMaybeNom :: Maybe (Nom [Name Int]) -> Bool
prop_transposeMaybeNom x' =
let y' = transposeMF (transposeFM x')
in case (x', y') of
(Nothing, Nothing) -> True
(Just l1', Just l2') -> unNom $ ((==) `on` fmap nameLabel) <$> l1' <*> l2'
_ -> False
prop_new' :: [Name Int] -> Bool
prop_new' l = (new :: Int -> (Name Int -> Bool) -> Bool) def $ \a -> new def $ \b -> (swpN a b l) == l
prop_not_new' :: [Name Int] -> Name Int -> Property
prop_not_new' l b = expectFailure $ new def $ \a -> (swpN a b l) == l
prop_new :: Int -> Int -> [Name Int] -> Bool
prop_new ta tb l = (new :: Int -> (Name Int -> Bool) -> Bool) ta $ \a -> new tb $ \b -> (swpN a b l) == l
prop_freshFor_notElem :: Name () -> [Name ()] -> Bool
prop_freshFor_notElem n ns = not (n `elem` ns) == (n `freshFor` ns)
iprop_support_nom :: forall a. (Support a, Swappable a) => [Atom] -> a -> Bool
iprop_support_nom atms a = supp ((atms @> a) :: Nom a) == (supp a) S.\\ (S.fromList atms)
prop_support_nom_atmlist :: [Atom] -> [Atom] -> Bool
prop_support_nom_atmlist = iprop_support_nom
prop_support_nom_nomatmlist :: [Atom] -> Nom [Atom] -> Bool
prop_support_nom_nomatmlist = iprop_support_nom
iprop_freshen_apart :: (Support a, Swappable a) => a -> Bool
iprop_freshen_apart a = unNom $ (kfreshen atTom a) >>= \a' -> return $ a' `apart` a
prop_freshen_apart_atmlist :: [Atom] -> Bool
prop_freshen_apart_atmlist = iprop_freshen_apart
prop_freshen_apart_nom_atmlist :: Nom [Atom] -> Bool
prop_freshen_apart_nom_atmlist = iprop_freshen_apart
prop_freshen_apart_disjoint :: [Atom] -> Bool
prop_freshen_apart_disjoint as = unNom $ (freshen as) >>= \as' -> return $ as' `LE.disjoint` as
prop_isTrivial_equal :: Nom [Atom] -> Bool
prop_isTrivial_equal x = isTrivialNomBySupp x == isTrivialNomByEq x
prop_isTrivial_sane :: Nom [Atom] -> Property
prop_isTrivial_sane x = expectFailure $ isTrivialNomBySupp x
prop_isTrivial_sane' :: Nom [Atom] -> Property
prop_isTrivial_sane' x = expectFailure $ isTrivialNomByEq x
deBruijnAcc :: KNom s a -> (KAtom s -> b) -> b -> (a, KAtom s -> b)
deBruijnAcc a' f b = exitWith (\atms a -> (a, \atm -> if (atm `elem` atms) then b else f atm)) a'
deBruijn1 :: Functor f => KNom s (f (KAtom s)) -> f Int
deBruijn1 a' = (deBruijnAcc a' (\_ -> 0) 1) & \(a, f) -> f <$> a
deBruijn2 :: Functor f => KNom s (KNom s (f (KAtom s)))-> f Int
deBruijn2 a'' = (deBruijnAcc a'' (\_ -> 0) 1) & \(a', f') -> (deBruijnAcc a' f' 2) & \(a, f) -> f <$> a
prop_transposeNomList :: Nom [Atom] -> Property
prop_transposeNomList x' = deBruijn1 x' === deBruijn1 (transposeFM (transposeMF x'))
prop_transposeNomNom :: Nom (Nom [Atom]) -> Property
prop_transposeNomNom x'' = deBruijn2 x'' === deBruijn2 (transposeMF $ transposeMF x'')