{-# LANGUAGE DataKinds              #-}
{-# LANGUAGE DeriveGeneric          #-}
{-# LANGUAGE FlexibleContexts       #-}
{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE ScopedTypeVariables    #-}
{-# LANGUAGE TypeSynonymInstances   #-}
{-# LANGUAGE TypeApplications       #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Language.Nominal.Properties.UnifySpec
    where
import Data.Set                      as S
import Test.QuickCheck
import Language.Nominal.Name
import Language.Nominal.NameSet
import Language.Nominal.Nom
import Language.Nominal.Binder
import Language.Nominal.Abs
import Language.Nominal.Unify
prop_l_l' :: [Name Int] -> [Name Int] -> Property
prop_l_l' ns' ns = expectFailure $ unifiablePerm ns ns'
prop_res_res :: [Atom] -> [Atom] -> [Atom] -> Bool
prop_res_res ns' ns x = kunifiablePerm atTom (restrict ns' ((ns @> x) :: Nom [Atom])) (restrict ns (ns' @> x))
prop_res_unres :: Nom [Name Int] -> Bool
prop_res_unres x' = x' @@! \atms x -> unifiablePerm x' $ atms @> x
prop_unify_ren :: [Name ()] -> [Name ()] -> Property
prop_unify_ren a b = let a' = Prelude.take 5 a 
                         b' = Prelude.take 5 b
                     in unifiablePerm a' b' ==> ren (unifyPerm a' b') a' === b'
prop_renId :: Atom -> Bool
prop_renId a = renExtend a a idRen == idRen
iprop_fresh_ren :: (UnifyPerm a, Support a, Swappable a, Eq a) => a -> Bool
iprop_fresh_ren a = let (atms :: [Atom]) = S.toList $ supp a in unNom $ do 
   atms' <- freshKAtoms atms
   let p = zip atms atms'
   return $ perm p a == ren (renFromList p) a
prop_fresh_ren_atmlistlist :: [[Atom]] -> Bool
prop_fresh_ren_atmlistlist = iprop_fresh_ren
prop_fresh_ren_absatmlist :: Abs () [Atom] -> Bool
prop_fresh_ren_absatmlist = iprop_fresh_ren