packages feed

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

-------------------------------------------------