nom-0.1.0.0: src/Language/Nominal/Properties/UnifySpec.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
-- {-# LANGUAGE PolyKinds #-}
{-# 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
-- | l is unifiable with l' for any l and l'
-- Should fail, taking e.g. l = [] and l' nonempty
prop_l_l' :: [Name Int] -> [Name Int] -> Property
prop_l_l' ns' ns = expectFailure $ unifiablePerm ns ns'
-- | ns @> ns' @> x is unifiable with ns' @> ns @> x
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))
-- | x' -> ns x -> res ns x unifies with x'
prop_res_unres :: Nom [Name Int] -> Bool
prop_res_unres x' = x' @@! \atms x -> unifiablePerm x' $ atms @> x
-- | Unifiers correctly calculated
prop_unify_ren :: [Name ()] -> [Name ()] -> Property
prop_unify_ren a b = let a' = Prelude.take 5 a -- control size so decent chance are unifiable
b' = Prelude.take 5 b
in unifiablePerm a' b' ==> ren (unifyPerm a' b') a' === b'
-- | 'idRen' equals 'idRen' extended with an identity mapping (since equality is on nub).
prop_renId :: Atom -> Bool
prop_renId a = renExtend a a idRen == idRen
-- | Permutations and freshening renamings coincide
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 -- Nom monad
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
-- TODO: arbitrary instance for Ren?