module AlphaProperties where
import Unbound.Generics.LocallyNameless (fv, aeq, Name, Alpha)
import Test.Tasty.QuickCheck (counterexample, Property, testProperty)
import Data.Typeable (Typeable)
import Data.Monoid (Any(..))
import Unbound.Generics.LocallyNameless.Internal.Fold (foldMapOf, toListOf)
isFreeIn :: (Typeable a, Alpha b) => Name a -> b -> Bool
isFreeIn = elementOf fv
where
elementOf l = anyOf l . (==)
anyOf l f = getAny . foldMapOf l (Any . f)
notFreeIn :: (Typeable a, Alpha b) => Name a -> b -> Bool
notFreeIn v = not . isFreeIn v
(=~=) :: (Alpha a, Show a) => a -> a -> Property
x =~= y = counterexample (show x ++ " not alpha equivalent to " ++ show y) (x `aeq` y)
(/~@) :: (Typeable a, Alpha b, Show b) => Name a -> b -> Property
v /~@ t = counterexample (show v ++ " is free in " ++ show t) (v `notFreeIn` t)