hermit-1.0.1: src/HERMIT/Libraries/WW.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module HERMIT.Libraries.WW (lemmas) where
import HERMIT.Lemma
import HERMIT.GHC hiding (($$), (<>))
import HERMIT.Kure
import HERMIT.Name
import HERMIT.Dictionary.Common
import HERMIT.Dictionary.Function
import HERMIT.Dictionary.GHC
import HERMIT.Dictionary.Reasoning
import Prelude hiding (abs)
lemmas :: LemmaLibrary
lemmas = workerWrapperLemmaT
-------------------------------------------------
-- | worker/wrapper
--
-- abs :: B -> A
-- rep :: A -> B
-- f :: A -> A
--
-- abs . rep = id \/ abs . rep . f = f \/ fix (abs . rep . f) = fix f
-----------------------------------------------------------------------------
-- fix f = abs (fix (rep . f . abs)) = abs (rep (fix f))
-- ^ 1B ^ ^ 2B ^
--
workerWrapperLemmaT :: LemmaLibrary
workerWrapperLemmaT = do
idId <- findIdT "Data.Function.id"
fixId <- findIdT "Data.Function.fix"
contextonlyT $ \ c -> do
-- aTv :: Var, aTy :: Type
[aTv, bTv] <- mapM newTyVar ["a","b"]
let [aTy, bTy] = map mkTyVarTy [aTv, bTv]
abs <- newIdH "abs" (bTy --> aTy)
rep <- newIdH "rep" (aTy --> bTy)
f <- newIdH "f" (aTy --> aTy)
-- abs . rep = id
lhsA <- inContextM c $ buildCompositionT (toCE abs) (toCE rep)
#if __GLASGOW_HASKELL__ > 710
let preA = lhsA === mkCoreApp (text "workerWrapperLemmaT") (toCE idId) (toCE aTv)
#else
let preA = lhsA === mkCoreApp (toCE idId) (toCE aTv)
#endif
-- abs . rep . f = f
repAfterF <- inContextM c $ buildCompositionT (toCE rep) (toCE f)
lhsB <- inContextM c $ buildCompositionT (toCE abs) repAfterF
let preB = lhsB === f
-- fix (abs . rep . f) = fix f
lhsC <- fixId $$ lhsB
fixf <- fixId $$ f
let preC = lhsC === fixf
-- 1B
fAfterAbs <- inContextM c $ buildCompositionT (toCE f) (toCE abs)
comp1B <- inContextM c $ buildCompositionT (toCE rep) fAfterAbs
rhs1B <- (abs $$) =<< (fixId $$ comp1B)
let oneB = fixf === rhs1B
-- 2B
rhs2B <- (abs $$) =<< (rep $$ fixf)
let twoB = fixf === rhs2B
return $ mconcat
[ newLemma "ww-split-1B" $
mkForall [aTv, bTv, abs, rep, f] $
("ww-split-1B-antecedent", preA \/ preB \/ preC) ==> oneB
, newLemma "ww-split-2B" $
mkForall [aTv, bTv, abs, rep, f] $
("ww-split-1B-antecedent", preA \/ preB \/ preC) ==> twoB
]
-------------------------------------------------
newTyVar :: MonadUnique m => String -> m TyVar
newTyVar nm = newTyVarH nm liftedTypeKind
-------------------------------------------------