-----------------------------------------------------------------------------
-- |
-- Module    : Data.SBV.TP.List
-- Copyright : (c) Levent Erkok
-- License   : BSD3
-- Maintainer: erkokl@gmail.com
-- Stability : experimental
--
-- A variety of TP proofs on list processing functions. Note that
-- these proofs only hold for finite lists. SMT-solvers do not model infinite
-- lists, and hence all claims are for finite (but arbitrary-length) lists.
-----------------------------------------------------------------------------

{-# LANGUAGE CPP                 #-}
{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE OverloadedLists     #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE QuasiQuotes         #-}
{-# LANGUAGE TypeAbstractions    #-}
{-# LANGUAGE TypeApplications    #-}

{-# OPTIONS_GHC -Wall -Werror #-}

module Data.SBV.TP.List (
     -- * Append
     appendNull, consApp, appendAssoc, initsLength, tailsLength, tailsAppend

     -- * Reverse
   , revLen, revApp, revCons, revSnoc, revRev, enumLen, revNM

     -- * Length
   , lengthTail, lenAppend, lenAppend2

     -- * Replicate
   , replicateLength

     -- * All and any
   , allAny

     -- * Map
   , mapEquiv, mapAppend, mapReverse, mapCompose

     -- * Foldr and foldl
   , foldrMapFusion, foldrFusion, foldrOverAppend, foldlOverAppend, foldrFoldlDuality, foldrFoldlDualityGeneralized, foldrFoldl
   , bookKeeping

     -- * Filter
   , filterAppend, filterConcat, takeDropWhile

     -- * Stutter removal
   , destutter, destutterIdempotent

     -- * Difference
   , appendDiff, diffAppend, diffDiff

     -- * Partition
   , partition1, partition2

    -- * Take and drop
   , take_take, drop_drop, take_drop, take_cons, take_map, drop_cons, drop_map, length_take, length_drop, take_all, drop_all
   , take_append, drop_append

   -- * Zip
   , map_fst_zip
   , map_snd_zip
   , map_fst_zip_take
   , map_snd_zip_take

   -- * Counting elements
   , count, countAppend, takeDropCount, countNonNeg, countElem, elemCount

   -- * Disjointness
   , disjoint, disjointDiff

   -- * Interleaving
   , interleave, uninterleave, interleaveLen, interleaveRoundTrip
 ) where

import Prelude (Integer, Bool, Eq, ($), Num(..), id, (.), flip)

import Data.SBV
import Data.SBV.List
import Data.SBV.Tuple
import Data.SBV.TP

#ifdef DOCTEST
-- $setup
-- >>> :set -XScopedTypeVariables
-- >>> :set -XTypeApplications
-- >>> import Data.SBV
-- >>> import Data.SBV.TP
-- >>> import Control.Exception
#endif

-- | @xs ++ [] == xs@
--
-- >>> runTP $ appendNull @Integer
-- Lemma: appendNull                       Q.E.D.
-- [Proven] appendNull :: Ɐxs ∷ [Integer] → Bool
appendNull :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
appendNull :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
appendNull = String
-> (Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"appendNull"
                   (\(Forall SList a
xs) -> SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
forall a. SymVal a => SList a
nil SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SList a
xs)
                   []

-- | @(x : xs) ++ ys == x : (xs ++ ys)@
--
-- >>> runTP $ consApp @Integer
-- Lemma: consApp                          Q.E.D.
-- [Proven] consApp :: Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
consApp :: forall a. SymVal a => TP (Proof (Forall "x" a -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
consApp :: forall a.
SymVal a =>
TP
  (Proof
     (Forall "x" a -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
consApp = String
-> (Forall "x" a -> Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> [ProofObj]
-> TP
     (Proof
        (Forall "x" a -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"consApp"
                (\(Forall SBV a
x) (Forall SList a
xs) (Forall SList a
ys) -> (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs) SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys))
                []

-- | @(xs ++ ys) ++ zs == xs ++ (ys ++ zs)@
--
-- >>> runTP $ appendAssoc @Integer
-- Lemma: appendAssoc                      Q.E.D.
-- [Proven] appendAssoc :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Ɐzs ∷ [Integer] → Bool
--
-- Surprisingly, z3 can prove this without any induction. (Since SBV's append translates directly to
-- the concatenation of sequences in SMTLib, it must trigger an internal heuristic in z3
-- that proves it right out-of-the-box!)
appendAssoc :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "zs" [a] -> SBool))
appendAssoc :: forall a.
SymVal a =>
TP
  (Proof
     (Forall "xs" [a] -> Forall "ys" [a] -> Forall "zs" [a] -> SBool))
appendAssoc =
   String
-> (Forall "xs" [a] -> Forall "ys" [a] -> Forall "zs" [a] -> SBool)
-> [ProofObj]
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "ys" [a] -> Forall "zs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"appendAssoc"
         (\(Forall SList a
xs) (Forall SList a
ys) (Forall SList a
zs) -> SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ (SList a
ys SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
zs) SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys) SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
zs)
         []

-- | @length (inits xs) == 1 + length xs@
--
-- >>> runTP $ initsLength @Integer
-- Inductive lemma (strong): initsLength
--   Step: Measure is non-negative         Q.E.D.
--   Step: 1                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] initsLength :: Ɐxs ∷ [Integer] → Bool
initsLength :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
initsLength :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
initsLength =
   String
-> (Forall "xs" [a] -> SBool)
-> MeasureArgs (Forall "xs" [a] -> SBool) Integer
-> (Proof (Forall "xs" [a] -> SBool)
    -> StepArgs (Forall "xs" [a] -> SBool) Integer)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a m t.
(SInductive a, Proposition a, Zero m, SymVal t,
 EqSymbolic (SBV t)) =>
String
-> a
-> MeasureArgs a m
-> (Proof a -> StepArgs a t)
-> TP (Proof a)
forall m t.
(Proposition (Forall "xs" [a] -> SBool), Zero m, SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> MeasureArgs (Forall "xs" [a] -> SBool) m
-> (Proof (Forall "xs" [a] -> SBool)
    -> StepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
sInduct String
"initsLength"
           (\(Forall SBV [a]
xs) -> SList [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV [a] -> SList [a]
forall a. SymVal a => SList a -> SList [a]
inits SBV [a]
xs) SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs)
           (forall a. SymVal a => SList a -> SBV Integer
length @a) ((Proof (Forall "xs" [a] -> SBool)
  -> StepArgs (Forall "xs" [a] -> SBool) Integer)
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (Forall "xs" [a] -> SBool)
    -> StepArgs (Forall "xs" [a] -> SBool) Integer)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
           \Proof (Forall "xs" [a] -> SBool)
ih SBV [a]
xs -> [] [SBool]
-> TPProofRaw (SBV Integer) -> (SBool, TPProofRaw (SBV Integer))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SList [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV [a] -> SList [a]
forall a. SymVal a => SList a -> SList [a]
inits SBV [a]
xs)
                        SBV Integer
-> Proof (Forall "xs" [a] -> SBool) -> Hinted (SBV Integer)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> SBool)
ih
                        TPProofRaw (SBV Integer)
-> ChainsTo (TPProofRaw (SBV Integer))
-> ChainsTo (TPProofRaw (SBV Integer))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs
                        SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV Integer)
TPProofRaw (SBV Integer)
forall a. TPProofRaw a
qed

-- | @length (tails xs) == 1 + length xs@
--
-- >>> runTP $ tailsLength @Integer
-- Inductive lemma: tailsLength
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] tailsLength :: Ɐxs ∷ [Integer] → Bool
tailsLength :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
tailsLength :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
tailsLength =
   String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) Integer)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"tailsLength"
          (\(Forall SBV [a]
xs) -> SList [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV [a] -> SList [a]
forall a. SymVal a => SList a -> SList [a]
tails SBV [a]
xs) SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) Integer)
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) Integer)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) -> [] [SBool]
-> TPProofRaw (SBV Integer) -> (SBool, TPProofRaw (SBV Integer))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SList [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV [a] -> SList [a]
forall a. SymVal a => SList a -> SList [a]
tails (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs))
                            SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SList [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV [a] -> SList [a]
forall a. SymVal a => SList a -> SList [a]
tails SBV [a]
xs SList [a] -> SList [a] -> SList [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ [SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs])
                            SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SList [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV [a] -> SList [a]
forall a. SymVal a => SList a -> SList [a]
tails SBV [a]
xs) SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV Integer
1
                            SBV Integer -> Proof SBool -> Hinted (SBV Integer)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                            TPProofRaw (SBV Integer)
-> ChainsTo (TPProofRaw (SBV Integer))
-> ChainsTo (TPProofRaw (SBV Integer))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV Integer
1
                            SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                            SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV Integer)
TPProofRaw (SBV Integer)
forall a. TPProofRaw a
qed

-- | @tails (xs ++ ys) == map (++ ys) (tails xs) ++ tail (tails ys)@
--
-- This property comes from Richard Bird's "Pearls of functional Algorithm Design" book, chapter 2.
-- Note that it is not exactly as stated there, as the definition of @tail@ Bird uses is different
-- than the standard Haskell function @tails@: Bird's version does not return the empty list as the
-- tail. So, we slightly modify it to fit the standard definition.
--
-- >>> runTP $ tailsAppend @Integer
-- Inductive lemma: base case
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Result:                               Q.E.D.
-- Lemma: helper
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Result:                               Q.E.D.
-- Inductive lemma: tailsAppend
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] tailsAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
tailsAppend :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
tailsAppend :: forall a.
SymVal a =>
TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
tailsAppend = do

   let -- Ideally, we would like to define appendEach like this:
       --
       --       appendEach xs ys = map (++ ys) xs
       --
       -- But capture of ys is not allowed when we use the higher-order
       -- function map in SBV. So, we create a closure instead.
       appendEach :: SList a -> SList [a] -> SList [a]
       appendEach :: SList a -> SBV [[a]] -> SBV [[a]]
appendEach SList a
ys = Closure (SList a) (SList a -> SList a) -> SBV [[a]] -> SBV [[a]]
forall func a b. SMap func a b => func -> SList a -> SList b
map (Closure (SList a) (SList a -> SList a) -> SBV [[a]] -> SBV [[a]])
-> Closure (SList a) (SList a -> SList a) -> SBV [[a]] -> SBV [[a]]
forall a b. (a -> b) -> a -> b
$ Closure { closureEnv :: SList a
closureEnv = SList a
ys
                                     , closureFun :: SList a -> SList a -> SList a
closureFun = \SList a
env SList a
xs -> SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
env
                                     }

   -- Even proving the base case of induction is hard due to recursive definition. So we first prove the base case by induction.
   Proof (Forall "ys" [a] -> SBool)
bc <- String
-> (Forall "ys" [a] -> SBool)
-> (Proof (IHType (Forall "ys" [a] -> SBool))
    -> IHArg (Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "ys" [a] -> SBool) [[a]])
-> TP (Proof (Forall "ys" [a] -> SBool))
forall t.
(Proposition (Forall "ys" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "ys" [a] -> SBool)
-> (Proof (IHType (Forall "ys" [a] -> SBool))
    -> IHArg (Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "ys" [a] -> SBool) t)
-> TP (Proof (Forall "ys" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"base case"
                (\(Forall @"ys" (SList a
ys :: SList a)) -> SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails SList a
ys SBV [[a]] -> SBV [[a]] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== [Item (SBV [[a]])
SList a
ys] SBV [[a]] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a
tail (SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails SList a
ys)) ((Proof (IHType (Forall "ys" [a] -> SBool))
  -> IHArg (Forall "ys" [a] -> SBool)
  -> IStepArgs (Forall "ys" [a] -> SBool) [[a]])
 -> TP (Proof (Forall "ys" [a] -> SBool)))
-> (Proof (IHType (Forall "ys" [a] -> SBool))
    -> IHArg (Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "ys" [a] -> SBool) [[a]])
-> TP (Proof (Forall "ys" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
                \Proof (IHType (Forall "ys" [a] -> SBool))
ih (SBV a
y, SList a
ys) -> [] [SBool]
-> TPProofRaw (SBV [[a]]) -> (SBool, TPProofRaw (SBV [[a]]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails (SBV a
y SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
ys)
                                  SBV [[a]] -> ChainsTo (SBV [[a]]) -> ChainsTo (SBV [[a]])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [SBV a
y SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
ys] SBV [[a]] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails SList a
ys
                                  SBV [[a]] -> Proof SBool -> Hinted (SBV [[a]])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "ys" [a] -> SBool))
ih
                                  TPProofRaw (SBV [[a]])
-> ChainsTo (TPProofRaw (SBV [[a]]))
-> ChainsTo (TPProofRaw (SBV [[a]]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [SBV a
y SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
ys] SBV [[a]] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SBV [[a]])
SList a
ys] SBV [[a]] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a
tail (SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails SList a
ys)
                                  SBV [[a]] -> ChainsTo (SBV [[a]]) -> ChainsTo (SBV [[a]])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [SBV a
y SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
ys] SBV [[a]] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a
tail (SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails (SBV a
y SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
ys))
                                  SBV [[a]] -> ChainsTo (SBV [[a]]) -> ChainsTo (SBV [[a]])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [[a]])
TPProofRaw (SBV [[a]])
forall a. TPProofRaw a
qed

   -- Also need a helper to relate how appendEach and tails work together
   Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool)
helper <- String
-> (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool)
-> StepArgs
     (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool) [[a]]
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool))
forall t.
(Proposition
   (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool)
-> StepArgs
     (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool) t
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool))
forall a t.
(Calc a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String -> a -> StepArgs a t -> TP (Proof a)
calc String
"helper"
                   (\(Forall @"xs" SList a
xs) (Forall @"ys" SList a
ys) (Forall @"x" SBV a
x) ->
                        SList a -> SBV [[a]] -> SBV [[a]]
appendEach SList a
ys (SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs)) SBV [[a]] -> SBV [[a]] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== [(SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs) SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys] SBV [[a]] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a -> SBV [[a]] -> SBV [[a]]
appendEach SList a
ys (SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails SList a
xs)) (StepArgs
   (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool) [[a]]
 -> TP
      (Proof
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool)))
-> StepArgs
     (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool) [[a]]
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool))
forall a b. (a -> b) -> a -> b
$
                   \SList a
xs SList a
ys SBV a
x -> [] [SBool]
-> TPProofRaw (SBV [[a]]) -> (SBool, TPProofRaw (SBV [[a]]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SList a -> SBV [[a]] -> SBV [[a]]
appendEach SList a
ys (SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs))
                                  SBV [[a]] -> ChainsTo (SBV [[a]]) -> ChainsTo (SBV [[a]])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SList a -> SBV [[a]] -> SBV [[a]]
appendEach SList a
ys ([SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs] SBV [[a]] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails SList a
xs)
                                  SBV [[a]] -> ChainsTo (SBV [[a]]) -> ChainsTo (SBV [[a]])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs) SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys] SBV [[a]] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a -> SBV [[a]] -> SBV [[a]]
appendEach SList a
ys (SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails SList a
xs)
                                  SBV [[a]] -> ChainsTo (SBV [[a]]) -> ChainsTo (SBV [[a]])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [[a]])
TPProofRaw (SBV [[a]])
forall a. TPProofRaw a
qed

   String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) [[a]])
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "ys" [a] -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"tailsAppend"
          (\(Forall SList a
xs) (Forall SList a
ys) -> SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails (SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys) SBV [[a]] -> SBV [[a]] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SList a -> SBV [[a]] -> SBV [[a]]
appendEach SList a
ys (SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails SList a
xs) SBV [[a]] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a
tail (SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails SList a
ys)) ((Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) [[a]])
 -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) [[a]])
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
ih (SBV a
x, SList a
xs) SList a
ys -> [Proof (Forall "ys" [a] -> SBool) -> SBool
forall a. Proof a -> SBool
assumptionFromProof Proof (Forall "ys" [a] -> SBool)
bc]
                         [SBool]
-> TPProofRaw (SBV [[a]]) -> (SBool, TPProofRaw (SBV [[a]]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails ((SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs) SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys)
                         SBV [[a]] -> ChainsTo (SBV [[a]]) -> ChainsTo (SBV [[a]])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys))
                         SBV [[a]] -> ChainsTo (SBV [[a]]) -> ChainsTo (SBV [[a]])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys)] SBV [[a]] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails (SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys)
                         SBV [[a]] -> Proof (Forall "ys" [a] -> SBool) -> Hinted (SBV [[a]])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
Proof (Forall "ys" [a] -> SBool)
ih
                         TPProofRaw (SBV [[a]])
-> ChainsTo (TPProofRaw (SBV [[a]]))
-> ChainsTo (TPProofRaw (SBV [[a]]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs) SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys] SBV [[a]] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a -> SBV [[a]] -> SBV [[a]]
appendEach SList a
ys (SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails SList a
xs) SBV [[a]] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a
tail (SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails SList a
ys)
                         SBV [[a]]
-> Proof
     (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool)
-> Hinted (SBV [[a]])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool)
helper
                         TPProofRaw (SBV [[a]])
-> ChainsTo (TPProofRaw (SBV [[a]]))
-> ChainsTo (TPProofRaw (SBV [[a]]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SList a -> SBV [[a]] -> SBV [[a]]
appendEach SList a
ys (SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs)) SBV [[a]] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SList a -> SList a
tail (SList a -> SBV [[a]]
forall a. SymVal a => SList a -> SList [a]
tails SList a
ys)
                         SBV [[a]] -> ChainsTo (SBV [[a]]) -> ChainsTo (SBV [[a]])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [[a]])
TPProofRaw (SBV [[a]])
forall a. TPProofRaw a
qed

-- | @length xs == length (reverse xs)@
--
-- >>> runTP $ revLen @Integer
-- Inductive lemma: revLen
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] revLen :: Ɐxs ∷ [Integer] → Bool
revLen :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
revLen :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
revLen = String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) Integer)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"revLen"
                (\(Forall SList a
xs) -> SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
xs) SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
xs) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) Integer)
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) Integer)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
                \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SList a
xs) -> [] [SBool]
-> TPProofRaw (SBV Integer) -> (SBool, TPProofRaw (SBV Integer))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs))
                                  SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SList a)
SBV a
x])
                                  SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
xs) SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length [Item (SList a)
SBV a
x]
                                  SBV Integer -> Proof SBool -> Hinted (SBV Integer)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                                  TPProofRaw (SBV Integer)
-> ChainsTo (TPProofRaw (SBV Integer))
-> ChainsTo (TPProofRaw (SBV Integer))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV Integer
1
                                  SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs)
                                  SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV Integer)
TPProofRaw (SBV Integer)
forall a. TPProofRaw a
qed

-- | @reverse (xs ++ ys) .== reverse ys ++ reverse xs@
--
-- >>> runTP $ revApp @Integer
-- Inductive lemma: revApp
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] revApp :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
revApp :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
revApp :: forall a.
SymVal a =>
TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
revApp = String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "ys" [a] -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"revApp"
                 (\(Forall SBV [a]
xs) (Forall SBV [a]
ys) -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys) SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse SBV [a]
ys SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) [a])
 -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
                 \Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) SBV [a]
ys -> [] [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse ((SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys)
                                      SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys))
                                      SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys) SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SBV [a])
SBV a
x]
                                      SBV [a] -> Proof (Forall "ys" [a] -> SBool) -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
Proof (Forall "ys" [a] -> SBool)
ih
                                      TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse SBV [a]
ys SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse SBV [a]
xs) SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SBV [a])
SBV a
x]
                                      SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse SBV [a]
ys SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SBV [a])
SBV a
x])
                                      SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse SBV [a]
ys SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                      SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed

-- | @reverse (x:xs) == reverse xs ++ [x]@
--
-- >>> runTP $ revCons @Integer
-- Lemma: revCons                          Q.E.D.
-- [Proven] revCons :: Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Bool
revCons :: forall a. SymVal a => TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
revCons :: forall a.
SymVal a =>
TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
revCons = String
-> (Forall "x" a -> Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"revCons"
                (\(Forall SBV a
x) (Forall SList a
xs) -> SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs) SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SList a)
SBV a
x])
                []

-- | @reverse (xs ++ [x]) == x : reverse xs@
--
-- >>> runTP $ revSnoc @Integer
-- Inductive lemma: revApp
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Result:                               Q.E.D.
-- Lemma: revSnoc                          Q.E.D.
-- [Proven] revSnoc :: Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Bool
revSnoc :: forall a. SymVal a => TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
revSnoc :: forall a.
SymVal a =>
TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
revSnoc = do
   Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
ra <- forall a.
SymVal a =>
TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
revApp @a

   String
-> (Forall "x" a -> Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"revSnoc"
         (\(Forall SBV a
x) (Forall SList a
xs) -> SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse (SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SList a)
SBV a
x]) SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
xs)
         [Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool) -> ProofObj
forall a. Proof a -> ProofObj
proofOf Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
ra]

-- | @reverse (reverse xs) == xs@
--
-- >>> runTP $ revRev @Integer
-- Inductive lemma: revApp
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Result:                               Q.E.D.
-- Inductive lemma: revRev
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] revRev :: Ɐxs ∷ [Integer] → Bool
revRev :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
revRev :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
revRev = do

   Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
ra <- forall a.
SymVal a =>
TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
revApp @a

   String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"revRev"
          (\(Forall SBV [a]
xs) -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse SBV [a]
xs) SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) [a])
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) -> [] [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs))
                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SBV [a])
SBV a
x])
                            SBV [a]
-> Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
ra
                            TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse [Item (SBV [a])
SBV a
x] SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
reverse SBV [a]
xs)
                            SBV [a] -> Proof SBool -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                            TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [Item (SBV [a])
SBV a
x] SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
xs
                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs
                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed

-- | \(\text{length } [n \dots m] = \max(0,\; m - n + 1)\)
--
-- The proof uses the metric @|m-n|@.
--
-- >>> runTP enumLen
-- Inductive lemma (strong): enumLen
--   Step: Measure is non-negative         Q.E.D.
--   Step: 1 (2 way case split)
--     Step: 1.1                           Q.E.D.
--     Step: 1.2.1                         Q.E.D.
--     Step: 1.2.2                         Q.E.D.
--     Step: 1.2.3                         Q.E.D.
--     Step: 1.2.4                         Q.E.D.
--     Step: 1.Completeness                Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] enumLen :: Ɐn ∷ Integer → Ɐm ∷ Integer → Bool
enumLen :: TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool))
enumLen :: TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool))
enumLen =
  String
-> (Forall "n" Integer -> Forall "m" Integer -> SBool)
-> MeasureArgs
     (Forall "n" Integer -> Forall "m" Integer -> SBool) Integer
-> (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
    -> StepArgs
         (Forall "n" Integer -> Forall "m" Integer -> SBool) Integer)
-> TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool))
forall a m t.
(SInductive a, Proposition a, Zero m, SymVal t,
 EqSymbolic (SBV t)) =>
String
-> a
-> MeasureArgs a m
-> (Proof a -> StepArgs a t)
-> TP (Proof a)
forall m t.
(Proposition (Forall "n" Integer -> Forall "m" Integer -> SBool),
 Zero m, SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "n" Integer -> Forall "m" Integer -> SBool)
-> MeasureArgs
     (Forall "n" Integer -> Forall "m" Integer -> SBool) m
-> (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
    -> StepArgs (Forall "n" Integer -> Forall "m" Integer -> SBool) t)
-> TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool))
sInduct String
"enumLen"
          (\(Forall SBV Integer
n) (Forall SBV Integer
m) -> SBV [Integer] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length [sEnum|n .. m|] SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer
0 SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smax` (SBV Integer
m SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SBV Integer
n SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV Integer
1))
          (\SBV Integer
n SBV Integer
m -> SBV Integer -> SBV Integer
forall a. Num a => a -> a
abs (SBV Integer
m SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SBV Integer
n)) ((Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
  -> StepArgs
       (Forall "n" Integer -> Forall "m" Integer -> SBool) Integer)
 -> TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)))
-> (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
    -> StepArgs
         (Forall "n" Integer -> Forall "m" Integer -> SBool) Integer)
-> TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
ih SBV Integer
n SBV Integer
m -> [] [SBool]
-> TPProofRaw (SBV Integer) -> (SBool, TPProofRaw (SBV Integer))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV [Integer] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length [sEnum|n+1 .. m|]
                        SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBool, TPProofRaw (SBV Integer))] -> TPProofRaw (SBV Integer)
forall a. [(SBool, TPProofRaw a)] -> TPProofRaw a
cases [ SBV Integer
nSBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+SBV Integer
1 SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>  SBV Integer
m SBool
-> TPProofRaw (SBV Integer) -> (SBool, TPProofRaw (SBV Integer))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> TPProofRaw (SBV Integer)
forall a. Trivial a => a
trivial
                                 , SBV Integer
nSBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+SBV Integer
1 SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.<= SBV Integer
m SBool
-> TPProofRaw (SBV Integer) -> (SBool, TPProofRaw (SBV Integer))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> SBV [Integer] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV Integer
nSBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+SBV Integer
1 SBV Integer -> SBV [Integer] -> SBV [Integer]
forall a. SymVal a => SBV a -> SList a -> SList a
.: [sEnum|n+2 .. m|])
                                              SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [Integer] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length [sEnum|n+2 .. m|]
                                              SBV Integer
-> Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
-> Hinted (SBV Integer)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
ih
                                              TPProofRaw (SBV Integer)
-> ChainsTo (TPProofRaw (SBV Integer))
-> ChainsTo (TPProofRaw (SBV Integer))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ (SBV Integer
0 SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smax` (SBV Integer
m SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- (SBV Integer
nSBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+SBV Integer
2) SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV Integer
1))
                                              SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer
0 SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smax` (SBV Integer
m SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- (SBV Integer
nSBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+SBV Integer
1) SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV Integer
1)
                                              SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV Integer)
TPProofRaw (SBV Integer)
forall a. TPProofRaw a
qed
                                 ]

-- | @reverse [n .. m] == [m, m-1 .. n]@
--
-- The proof uses the metric @|m-n|@.
--
-- >>> runTP $ revNM
-- Inductive lemma (strong): helper
--   Step: Measure is non-negative         Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Result:                               Q.E.D.
-- Inductive lemma (strong): revNM
--   Step: Measure is non-negative         Q.E.D.
--   Step: 1 (2 way case split)
--     Step: 1.1                           Q.E.D.
--     Step: 1.2.1                         Q.E.D.
--     Step: 1.2.2                         Q.E.D.
--     Step: 1.2.3                         Q.E.D.
--     Step: 1.2.4                         Q.E.D.
--     Step: 1.Completeness                Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] revNM :: Ɐn ∷ Integer → Ɐm ∷ Integer → Bool
revNM :: TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool))
revNM :: TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool))
revNM = do

  Proof (Forall "m" Integer -> Forall "n" Integer -> SBool)
helper <- String
-> (Forall "m" Integer -> Forall "n" Integer -> SBool)
-> MeasureArgs
     (Forall "m" Integer -> Forall "n" Integer -> SBool) Integer
-> (Proof (Forall "m" Integer -> Forall "n" Integer -> SBool)
    -> StepArgs
         (Forall "m" Integer -> Forall "n" Integer -> SBool) [Integer])
-> TP (Proof (Forall "m" Integer -> Forall "n" Integer -> SBool))
forall a m t.
(SInductive a, Proposition a, Zero m, SymVal t,
 EqSymbolic (SBV t)) =>
String
-> a
-> MeasureArgs a m
-> (Proof a -> StepArgs a t)
-> TP (Proof a)
forall m t.
(Proposition (Forall "m" Integer -> Forall "n" Integer -> SBool),
 Zero m, SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "m" Integer -> Forall "n" Integer -> SBool)
-> MeasureArgs
     (Forall "m" Integer -> Forall "n" Integer -> SBool) m
-> (Proof (Forall "m" Integer -> Forall "n" Integer -> SBool)
    -> StepArgs (Forall "m" Integer -> Forall "n" Integer -> SBool) t)
-> TP (Proof (Forall "m" Integer -> Forall "n" Integer -> SBool))
sInduct String
"helper"
                    (\(Forall @"m" (SBV Integer
m :: SInteger)) (Forall @"n" SBV Integer
n) ->
                          SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.< SBV Integer
m SBool -> SBool -> SBool
.=> [sEnum|m, m-1 .. n+1|] SBV [Integer] -> SBV [Integer] -> SBV [Integer]
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SBV [Integer])
SBV Integer
n] SBV [Integer] -> SBV [Integer] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== [sEnum|m, m-1 .. n|])
                    (\SBV Integer
m SBV Integer
n -> SBV Integer -> SBV Integer
forall a. Num a => a -> a
abs (SBV Integer
m SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SBV Integer
n)) ((Proof (Forall "m" Integer -> Forall "n" Integer -> SBool)
  -> StepArgs
       (Forall "m" Integer -> Forall "n" Integer -> SBool) [Integer])
 -> TP (Proof (Forall "m" Integer -> Forall "n" Integer -> SBool)))
-> (Proof (Forall "m" Integer -> Forall "n" Integer -> SBool)
    -> StepArgs
         (Forall "m" Integer -> Forall "n" Integer -> SBool) [Integer])
-> TP (Proof (Forall "m" Integer -> Forall "n" Integer -> SBool))
forall a b. (a -> b) -> a -> b
$
                    \Proof (Forall "m" Integer -> Forall "n" Integer -> SBool)
ih SBV Integer
m SBV Integer
n -> [SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.< SBV Integer
m] [SBool]
-> TPProofRaw (SBV [Integer])
-> (SBool, TPProofRaw (SBV [Integer]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- [sEnum|m, m-1 .. n+1|] SBV [Integer] -> SBV [Integer] -> SBV [Integer]
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SBV [Integer])
SBV Integer
n]
                                        SBV [Integer]
-> ChainsTo (SBV [Integer]) -> ChainsTo (SBV [Integer])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer
m SBV Integer -> SBV [Integer] -> SBV [Integer]
forall a. SymVal a => SBV a -> SList a -> SList a
.: [sEnum|m-1, m-2 .. n+1|] SBV [Integer] -> SBV [Integer] -> SBV [Integer]
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SBV [Integer])
SBV Integer
n]
                                        SBV [Integer]
-> Proof (Forall "m" Integer -> Forall "n" Integer -> SBool)
-> Hinted (SBV [Integer])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "m" Integer -> Forall "n" Integer -> SBool)
ih
                                        TPProofRaw (SBV [Integer])
-> ChainsTo (TPProofRaw (SBV [Integer]))
-> ChainsTo (TPProofRaw (SBV [Integer]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer
m SBV Integer -> SBV [Integer] -> SBV [Integer]
forall a. SymVal a => SBV a -> SList a -> SList a
.: [sEnum|m-1, m-2 .. n|]
                                        SBV [Integer]
-> ChainsTo (SBV [Integer]) -> ChainsTo (SBV [Integer])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [sEnum|m, m-1 .. n|]
                                        SBV [Integer]
-> ChainsTo (SBV [Integer]) -> ChainsTo (SBV [Integer])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [Integer])
TPProofRaw (SBV [Integer])
forall a. TPProofRaw a
qed

  String
-> (Forall "n" Integer -> Forall "m" Integer -> SBool)
-> MeasureArgs
     (Forall "n" Integer -> Forall "m" Integer -> SBool) Integer
-> (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
    -> StepArgs
         (Forall "n" Integer -> Forall "m" Integer -> SBool) [Integer])
-> TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool))
forall a m t.
(SInductive a, Proposition a, Zero m, SymVal t,
 EqSymbolic (SBV t)) =>
String
-> a
-> MeasureArgs a m
-> (Proof a -> StepArgs a t)
-> TP (Proof a)
forall m t.
(Proposition (Forall "n" Integer -> Forall "m" Integer -> SBool),
 Zero m, SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "n" Integer -> Forall "m" Integer -> SBool)
-> MeasureArgs
     (Forall "n" Integer -> Forall "m" Integer -> SBool) m
-> (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
    -> StepArgs (Forall "n" Integer -> Forall "m" Integer -> SBool) t)
-> TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool))
sInduct String
"revNM"
          (\(Forall SBV Integer
n) (Forall SBV Integer
m) -> SBV [Integer] -> SBV [Integer]
forall a. SymVal a => SList a -> SList a
reverse [sEnum|n .. m|] SBV [Integer] -> SBV [Integer] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== [sEnum|m, m-1 .. n|])
          (\SBV Integer
n SBV Integer
m -> SBV Integer -> SBV Integer
forall a. Num a => a -> a
abs (SBV Integer
m SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SBV Integer
n)) ((Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
  -> StepArgs
       (Forall "n" Integer -> Forall "m" Integer -> SBool) [Integer])
 -> TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)))
-> (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
    -> StepArgs
         (Forall "n" Integer -> Forall "m" Integer -> SBool) [Integer])
-> TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
ih SBV Integer
n SBV Integer
m -> [] [SBool]
-> TPProofRaw (SBV [Integer])
-> (SBool, TPProofRaw (SBV [Integer]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV [Integer] -> SBV [Integer]
forall a. SymVal a => SList a -> SList a
reverse [sEnum|n .. m|]
                        SBV [Integer]
-> ChainsTo (SBV [Integer]) -> ChainsTo (SBV [Integer])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBool, TPProofRaw (SBV [Integer]))] -> TPProofRaw (SBV [Integer])
forall a. [(SBool, TPProofRaw a)] -> TPProofRaw a
cases [ SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>  SBV Integer
m SBool
-> TPProofRaw (SBV [Integer])
-> (SBool, TPProofRaw (SBV [Integer]))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> TPProofRaw (SBV [Integer])
forall a. Trivial a => a
trivial
                                 , SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.<= SBV Integer
m SBool
-> TPProofRaw (SBV [Integer])
-> (SBool, TPProofRaw (SBV [Integer]))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> SBV [Integer] -> SBV [Integer]
forall a. SymVal a => SList a -> SList a
reverse (SBV Integer
n SBV Integer -> SBV [Integer] -> SBV [Integer]
forall a. SymVal a => SBV a -> SList a -> SList a
.: [sEnum|(n+1) .. m|])
                                            SBV [Integer]
-> ChainsTo (SBV [Integer]) -> ChainsTo (SBV [Integer])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV [Integer] -> SBV [Integer]
forall a. SymVal a => SList a -> SList a
reverse [sEnum|(n+1) .. m|] SBV [Integer] -> SBV [Integer] -> SBV [Integer]
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SBV [Integer])
SBV Integer
n]
                                            SBV [Integer]
-> Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
-> Hinted (SBV [Integer])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "n" Integer -> Forall "m" Integer -> SBool)
ih
                                            TPProofRaw (SBV [Integer])
-> ChainsTo (TPProofRaw (SBV [Integer]))
-> ChainsTo (TPProofRaw (SBV [Integer]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [sEnum|m, m-1 .. n+1|] SBV [Integer] -> SBV [Integer] -> SBV [Integer]
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SBV [Integer])
SBV Integer
n]
                                            SBV [Integer]
-> Proof (Forall "m" Integer -> Forall "n" Integer -> SBool)
-> Hinted (SBV [Integer])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "m" Integer -> Forall "n" Integer -> SBool)
helper
                                            TPProofRaw (SBV [Integer])
-> ChainsTo (TPProofRaw (SBV [Integer]))
-> ChainsTo (TPProofRaw (SBV [Integer]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [sEnum|m, m-1 .. n|]
                                            SBV [Integer]
-> ChainsTo (SBV [Integer]) -> ChainsTo (SBV [Integer])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [Integer])
TPProofRaw (SBV [Integer])
forall a. TPProofRaw a
qed
                                 ]

-- | @length (x : xs) == 1 + length xs@
--
-- >>> runTP $ lengthTail @Integer
-- Lemma: lengthTail                       Q.E.D.
-- [Proven] lengthTail :: Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Bool
lengthTail :: forall a. SymVal a => TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
lengthTail :: forall a.
SymVal a =>
TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
lengthTail = String
-> (Forall "x" a -> Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"lengthTail"
                   (\(Forall SBV a
x) (Forall SBV [a]
xs) -> SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs)
                   []

-- | @length (xs ++ ys) == length xs + length ys@
--
-- >>> runTP $ lenAppend @Integer
-- Lemma: lenAppend                        Q.E.D.
-- [Proven] lenAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
lenAppend :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
lenAppend :: forall a.
SymVal a =>
TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
lenAppend = String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"lenAppend"
                  (\(Forall SBV [a]
xs) (Forall SBV [a]
ys) -> SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys) SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
ys)
                  []

-- | @length xs == length ys -> length (xs ++ ys) == 2 * length xs@
--
-- >>> runTP $ lenAppend2 @Integer
-- Lemma: lenAppend2                       Q.E.D.
-- [Proven] lenAppend2 :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
lenAppend2 :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
lenAppend2 :: forall a.
SymVal a =>
TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
lenAppend2 = String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"lenAppend2"
                   (\(Forall SBV [a]
xs) (Forall SBV [a]
ys) -> SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
ys SBool -> SBool -> SBool
.=> SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys) SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer
2 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
* SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs)
                   []

-- | @length (replicate k x) == max (0, k)@
--
-- >>> runTP $ replicateLength @Integer
-- Inductive lemma: replicateLength
--   Step: Base                            Q.E.D.
--   Step: 1 (2 way case split)
--     Step: 1.1                           Q.E.D.
--     Step: 1.2.1                         Q.E.D.
--     Step: 1.2.2                         Q.E.D.
--     Step: 1.2.3                         Q.E.D.
--     Step: 1.2.4                         Q.E.D.
--     Step: 1.Completeness                Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] replicateLength :: Ɐk ∷ Integer → Ɐx ∷ Integer → Bool
replicateLength :: forall a. SymVal a => TP (Proof (Forall "k" Integer -> Forall "x" a -> SBool))
replicateLength :: forall a.
SymVal a =>
TP (Proof (Forall "k" Integer -> Forall "x" a -> SBool))
replicateLength = String
-> (Forall "k" Integer -> Forall "x" a -> SBool)
-> (Proof (IHType (Forall "k" Integer -> Forall "x" a -> SBool))
    -> IHArg (Forall "k" Integer -> Forall "x" a -> SBool)
    -> IStepArgs (Forall "k" Integer -> Forall "x" a -> SBool) Integer)
-> TP (Proof (Forall "k" Integer -> Forall "x" a -> SBool))
forall t.
(Proposition (Forall "k" Integer -> Forall "x" a -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "k" Integer -> Forall "x" a -> SBool)
-> (Proof (IHType (Forall "k" Integer -> Forall "x" a -> SBool))
    -> IHArg (Forall "k" Integer -> Forall "x" a -> SBool)
    -> IStepArgs (Forall "k" Integer -> Forall "x" a -> SBool) t)
-> TP (Proof (Forall "k" Integer -> Forall "x" a -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"replicateLength"
                         (\(Forall SBV Integer
k) (Forall SBV a
x) -> SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV Integer -> SBV a -> SList a
forall a. SymVal a => SBV Integer -> SBV a -> SList a
replicate SBV Integer
k SBV a
x) SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer
0 SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smax` SBV Integer
k) ((Proof (IHType (Forall "k" Integer -> Forall "x" a -> SBool))
  -> IHArg (Forall "k" Integer -> Forall "x" a -> SBool)
  -> IStepArgs (Forall "k" Integer -> Forall "x" a -> SBool) Integer)
 -> TP (Proof (Forall "k" Integer -> Forall "x" a -> SBool)))
-> (Proof (IHType (Forall "k" Integer -> Forall "x" a -> SBool))
    -> IHArg (Forall "k" Integer -> Forall "x" a -> SBool)
    -> IStepArgs (Forall "k" Integer -> Forall "x" a -> SBool) Integer)
-> TP (Proof (Forall "k" Integer -> Forall "x" a -> SBool))
forall a b. (a -> b) -> a -> b
$
                         \Proof (IHType (Forall "k" Integer -> Forall "x" a -> SBool))
ih IHArg (Forall "k" Integer -> Forall "x" a -> SBool)
k SBV a
x -> [] [SBool]
-> TPProofRaw (SBV Integer) -> (SBool, TPProofRaw (SBV Integer))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV Integer -> SBV a -> SList a
forall a. SymVal a => SBV Integer -> SBV a -> SList a
replicate (SBV Integer
IHArg (Forall "k" Integer -> Forall "x" a -> SBool)
kSBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+SBV Integer
1) SBV a
x)
                                       SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBool, TPProofRaw (SBV Integer))] -> TPProofRaw (SBV Integer)
forall a. [(SBool, TPProofRaw a)] -> TPProofRaw a
cases [ SBV Integer
IHArg (Forall "k" Integer -> Forall "x" a -> SBool)
k SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.< SBV Integer
0  SBool
-> TPProofRaw (SBV Integer) -> (SBool, TPProofRaw (SBV Integer))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> TPProofRaw (SBV Integer)
forall a. Trivial a => a
trivial
                                                , SBV Integer
IHArg (Forall "k" Integer -> Forall "x" a -> SBool)
k SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= SBV Integer
0 SBool
-> TPProofRaw (SBV Integer) -> (SBool, TPProofRaw (SBV Integer))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV Integer -> SBV a -> SList a
forall a. SymVal a => SBV Integer -> SBV a -> SList a
replicate SBV Integer
IHArg (Forall "k" Integer -> Forall "x" a -> SBool)
k SBV a
x)
                                                           SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV Integer -> SBV a -> SList a
forall a. SymVal a => SBV Integer -> SBV a -> SList a
replicate SBV Integer
IHArg (Forall "k" Integer -> Forall "x" a -> SBool)
k SBV a
x)
                                                           SBV Integer
-> Proof (Forall "x" a -> SBool) -> Hinted (SBV Integer)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "k" Integer -> Forall "x" a -> SBool))
Proof (Forall "x" a -> SBool)
ih
                                                           TPProofRaw (SBV Integer)
-> ChainsTo (TPProofRaw (SBV Integer))
-> ChainsTo (TPProofRaw (SBV Integer))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV Integer
0 SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smax` SBV Integer
IHArg (Forall "k" Integer -> Forall "x" a -> SBool)
k
                                                           SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer
0 SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smax` (SBV Integer
IHArg (Forall "k" Integer -> Forall "x" a -> SBool)
kSBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+SBV Integer
1)
                                                           SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV Integer)
TPProofRaw (SBV Integer)
forall a. TPProofRaw a
qed
                                                ]

-- | @not (all id xs) == any not xs@
--
-- A list of booleans is not all true, if any of them is false.
--
-- >>> runTP allAny
-- Inductive lemma: allAny
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] allAny :: Ɐxs ∷ [Bool] → Bool
allAny :: TP (Proof (Forall "xs" [Bool] -> SBool))
allAny :: TP (Proof (Forall "xs" [Bool] -> SBool))
allAny = String
-> (Forall "xs" [Bool] -> SBool)
-> (Proof (IHType (Forall "xs" [Bool] -> SBool))
    -> IHArg (Forall "xs" [Bool] -> SBool)
    -> IStepArgs (Forall "xs" [Bool] -> SBool) Bool)
-> TP (Proof (Forall "xs" [Bool] -> SBool))
forall t.
(Proposition (Forall "xs" [Bool] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [Bool] -> SBool)
-> (Proof (IHType (Forall "xs" [Bool] -> SBool))
    -> IHArg (Forall "xs" [Bool] -> SBool)
    -> IStepArgs (Forall "xs" [Bool] -> SBool) t)
-> TP (Proof (Forall "xs" [Bool] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"allAny"
                (\(Forall SBV [Bool]
xs) -> SBool -> SBool
sNot ((SBool -> SBool) -> SBV [Bool] -> SBool
forall a. SymVal a => (SBV a -> SBool) -> SList a -> SBool
all SBool -> SBool
forall a. a -> a
id SBV [Bool]
xs) SBool -> SBool -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBool -> SBool) -> SBV [Bool] -> SBool
forall a. SymVal a => (SBV a -> SBool) -> SList a -> SBool
any SBool -> SBool
sNot SBV [Bool]
xs) ((Proof (IHType (Forall "xs" [Bool] -> SBool))
  -> IHArg (Forall "xs" [Bool] -> SBool)
  -> IStepArgs (Forall "xs" [Bool] -> SBool) Bool)
 -> TP (Proof (Forall "xs" [Bool] -> SBool)))
-> (Proof (IHType (Forall "xs" [Bool] -> SBool))
    -> IHArg (Forall "xs" [Bool] -> SBool)
    -> IStepArgs (Forall "xs" [Bool] -> SBool) Bool)
-> TP (Proof (Forall "xs" [Bool] -> SBool))
forall a b. (a -> b) -> a -> b
$
                \Proof (IHType (Forall "xs" [Bool] -> SBool))
ih (SBool
x, SBV [Bool]
xs) -> [] [SBool] -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBool -> SBool
sNot ((SBool -> SBool) -> SBV [Bool] -> SBool
forall a. SymVal a => (SBV a -> SBool) -> SList a -> SBool
all SBool -> SBool
forall a. a -> a
id (SBool
x SBool -> SBV [Bool] -> SBV [Bool]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [Bool]
xs))
                                  SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBool
sNot (SBool
x SBool -> SBool -> SBool
.&& (SBool -> SBool) -> SBV [Bool] -> SBool
forall a. SymVal a => (SBV a -> SBool) -> SList a -> SBool
all SBool -> SBool
forall a. a -> a
id SBV [Bool]
xs)
                                  SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBool -> SBool
sNot SBool
x SBool -> SBool -> SBool
.|| SBool -> SBool
sNot ((SBool -> SBool) -> SBV [Bool] -> SBool
forall a. SymVal a => (SBV a -> SBool) -> SList a -> SBool
all SBool -> SBool
forall a. a -> a
id SBV [Bool]
xs))
                                  SBool -> Proof SBool -> Hinted SBool
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [Bool] -> SBool))
ih
                                  TPProofRaw SBool
-> ChainsTo (TPProofRaw SBool) -> ChainsTo (TPProofRaw SBool)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBool
sNot SBool
x SBool -> SBool -> SBool
.|| (SBool -> SBool) -> SBV [Bool] -> SBool
forall a. SymVal a => (SBV a -> SBool) -> SList a -> SBool
any SBool -> SBool
sNot SBV [Bool]
xs
                                  SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBool -> SBool) -> SBV [Bool] -> SBool
forall a. SymVal a => (SBV a -> SBool) -> SList a -> SBool
any SBool -> SBool
sNot (SBool
x SBool -> SBV [Bool] -> SBV [Bool]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [Bool]
xs)
                                  SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo SBool
TPProofRaw SBool
forall a. TPProofRaw a
qed

-- | @f == g ==> map f xs == map g xs@
--
-- >>> runTP $ mapEquiv @Integer @Integer (uninterpret "f") (uninterpret "g")
-- Inductive lemma: mapEquiv
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] mapEquiv :: Ɐxs ∷ [Integer] → Bool
mapEquiv :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b) -> (SBV a -> SBV b) -> TP (Proof (Forall "xs" [a] -> SBool))
mapEquiv :: forall a b.
(SymVal a, SymVal b) =>
(SBV a -> SBV b)
-> (SBV a -> SBV b) -> TP (Proof (Forall "xs" [a] -> SBool))
mapEquiv SBV a -> SBV b
f SBV a -> SBV b
g = do
   let f'eq'g :: SBool
       f'eq'g :: SBool
f'eq'g = (Forall Any a -> SBool) -> SBool
forall a. QuantifiedBool a => a -> SBool
quantifiedBool ((Forall Any a -> SBool) -> SBool)
-> (Forall Any a -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \(Forall SBV a
x) -> SBV a -> SBV b
f SBV a
x SBV b -> SBV b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a -> SBV b
g SBV a
x

   String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) Bool)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"mapEquiv"
          (\(Forall SBV [a]
xs) -> SBool
f'eq'g SBool -> SBool -> SBool
.=> (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
g SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) Bool)
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) Bool)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) -> [Item [SBool]
SBool
f'eq'g] [SBool] -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
g (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                  SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV b
f SBV a
x SBV b -> SList b -> SList b
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a -> SBV b
g SBV a
x SBV b -> SList b -> SList b
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
g SBV [a]
xs
                                  SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV b
f SBV a
x SBV b -> SList b -> SList b
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a -> SBV b
f SBV a
x SBV b -> SList b -> SList b
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
g SBV [a]
xs
                                  SBool -> Proof SBool -> Hinted SBool
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                                  TPProofRaw SBool
-> ChainsTo (TPProofRaw SBool) -> ChainsTo (TPProofRaw SBool)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV b
f SBV a
x SBV b -> SList b -> SList b
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a -> SBV b
f SBV a
x SBV b -> SList b -> SList b
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs
                                  SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                  SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo SBool
TPProofRaw SBool
forall a. TPProofRaw a
qed

-- | @map f (xs ++ ys) == map f xs ++ map f ys@
--
-- >>> runTP $ mapAppend @Integer @Integer (uninterpret "f")
-- Inductive lemma: mapAppend
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] mapAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
mapAppend :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b) -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
mapAppend :: forall a b.
(SymVal a, SymVal b) =>
(SBV a -> SBV b)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
mapAppend SBV a -> SBV b
f =
   String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) [b])
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "ys" [a] -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"mapAppend"
          (\(Forall SBV [a]
xs) (Forall SBV [a]
ys) -> (SBV a -> SBV b) -> SBV [a] -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys) SBV [b] -> SBV [b] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV b) -> SBV [a] -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs SBV [b] -> SBV [b] -> SBV [b]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBV b) -> SBV [a] -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
ys) ((Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) [b])
 -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) [b])
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) SBV [a]
ys -> [] [SBool] -> TPProofRaw (SBV [b]) -> (SBool, TPProofRaw (SBV [b]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a -> SBV b) -> SBV [a] -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f ((SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys)
                               SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b) -> SBV [a] -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys))
                             SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV b
f SBV a
x SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys)
                             SBV [b] -> Proof (Forall "ys" [a] -> SBool) -> Hinted (SBV [b])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
Proof (Forall "ys" [a] -> SBool)
ih
                             TPProofRaw (SBV [b])
-> ChainsTo (TPProofRaw (SBV [b]))
-> ChainsTo (TPProofRaw (SBV [b]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV b
f SBV a
x SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: ((SBV a -> SBV b) -> SBV [a] -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs  SBV [b] -> SBV [b] -> SBV [b]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBV b) -> SBV [a] -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
ys)
                             SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b
f SBV a
x SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs) SBV [b] -> SBV [b] -> SBV [b]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBV b) -> SBV [a] -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
ys
                             SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b) -> SBV [a] -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV [b] -> SBV [b] -> SBV [b]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBV b) -> SBV [a] -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
ys
                             SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [b])
TPProofRaw (SBV [b])
forall a. TPProofRaw a
qed

-- | @map f . reverse == reverse . map f@
--
-- >>> runTP $ mapReverse @Integer @String (uninterpret "f")
-- Inductive lemma: mapAppend
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Result:                               Q.E.D.
-- Inductive lemma: mapReverse
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Step: 6                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] mapReverse :: Ɐxs ∷ [Integer] → Bool
mapReverse :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b) -> TP (Proof (Forall "xs" [a] -> SBool))
mapReverse :: forall a b.
(SymVal a, SymVal b) =>
(SBV a -> SBV b) -> TP (Proof (Forall "xs" [a] -> SBool))
mapReverse SBV a -> SBV b
f = do
     Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
mApp <- (SBV a -> SBV b)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a b.
(SymVal a, SymVal b) =>
(SBV a -> SBV b)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
mapAppend SBV a -> SBV b
f

     String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [b])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"mapReverse"
            (\(Forall SList a
xs) -> SBV [b] -> SBV [b]
forall a. SymVal a => SList a -> SList a
reverse ((SBV a -> SBV b) -> SList a -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SList a
xs) SBV [b] -> SBV [b] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV b) -> SList a -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
xs)) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) [b])
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [b])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
            \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SList a
xs) -> [] [SBool] -> TPProofRaw (SBV [b]) -> (SBool, TPProofRaw (SBV [b]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV [b] -> SBV [b]
forall a. SymVal a => SList a -> SList a
reverse ((SBV a -> SBV b) -> SList a -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs))
                              SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV [b] -> SBV [b]
forall a. SymVal a => SList a -> SList a
reverse (SBV a -> SBV b
f SBV a
x SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SList a -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SList a
xs)
                              SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV [b] -> SBV [b]
forall a. SymVal a => SList a -> SList a
reverse ((SBV a -> SBV b) -> SList a -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SList a
xs) SBV [b] -> SBV [b] -> SBV [b]
forall a. SymVal a => SList a -> SList a -> SList a
++ [SBV a -> SBV b
f SBV a
x]
                              SBV [b] -> Proof SBool -> Hinted (SBV [b])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                              TPProofRaw (SBV [b])
-> ChainsTo (TPProofRaw (SBV [b]))
-> ChainsTo (TPProofRaw (SBV [b]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b) -> SList a -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
xs) SBV [b] -> SBV [b] -> SBV [b]
forall a. SymVal a => SList a -> SList a -> SList a
++ [SBV a -> SBV b
f SBV a
x]
                              SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b) -> SList a -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
xs) SBV [b] -> SBV [b] -> SBV [b]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBV b) -> SList a -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f [Item (SList a)
SBV a
x]
                              SBV [b]
-> Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> Hinted (SBV [b])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
mApp
                              TPProofRaw (SBV [b])
-> ChainsTo (TPProofRaw (SBV [b]))
-> ChainsTo (TPProofRaw (SBV [b]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b) -> SList a -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SList a)
SBV a
x])
                              SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b) -> SList a -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs))
                              SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [b])
TPProofRaw (SBV [b])
forall a. TPProofRaw a
qed

-- | @map f . map g == map (f . g)@
--
-- >>> runTP $ mapCompose @Integer @Bool @String (uninterpret "f") (uninterpret "g")
-- Inductive lemma: mapCompose
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] mapCompose :: Ɐxs ∷ [Integer] → Bool
mapCompose :: forall a b c. (SymVal a, SymVal b, SymVal c) => (SBV a -> SBV b) -> (SBV b -> SBV c) -> TP (Proof (Forall "xs" [a] -> SBool))
mapCompose :: forall a b c.
(SymVal a, SymVal b, SymVal c) =>
(SBV a -> SBV b)
-> (SBV b -> SBV c) -> TP (Proof (Forall "xs" [a] -> SBool))
mapCompose SBV a -> SBV b
f SBV b -> SBV c
g =
  String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [c])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"mapCompose"
         (\(Forall SBV [a]
xs) -> (SBV b -> SBV c) -> SList b -> SBV [c]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV b -> SBV c
g ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs) SBV [c] -> SBV [c] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV c) -> SBV [a] -> SBV [c]
forall func a b. SMap func a b => func -> SList a -> SList b
map (SBV b -> SBV c
g (SBV b -> SBV c) -> (SBV a -> SBV b) -> SBV a -> SBV c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBV a -> SBV b
f) SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) [c])
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [c])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
         \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) -> [] [SBool] -> TPProofRaw (SBV [c]) -> (SBool, TPProofRaw (SBV [c]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV b -> SBV c) -> SList b -> SBV [c]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV b -> SBV c
g ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs))
                           SBV [c] -> ChainsTo (SBV [c]) -> ChainsTo (SBV [c])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV c) -> SList b -> SBV [c]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV b -> SBV c
g (SBV a -> SBV b
f SBV a
x SBV b -> SList b -> SList b
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs)
                           SBV [c] -> ChainsTo (SBV [c]) -> ChainsTo (SBV [c])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV b -> SBV c
g (SBV a -> SBV b
f SBV a
x) SBV c -> SBV [c] -> SBV [c]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV b -> SBV c) -> SList b -> SBV [c]
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV b -> SBV c
g ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs)
                           SBV [c] -> Proof SBool -> Hinted (SBV [c])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                           TPProofRaw (SBV [c])
-> ChainsTo (TPProofRaw (SBV [c]))
-> ChainsTo (TPProofRaw (SBV [c]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV b -> SBV c
g (SBV a -> SBV b
f SBV a
x) SBV c -> SBV [c] -> SBV [c]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV c) -> SBV [a] -> SBV [c]
forall func a b. SMap func a b => func -> SList a -> SList b
map (SBV b -> SBV c
g (SBV b -> SBV c) -> (SBV a -> SBV b) -> SBV a -> SBV c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBV a -> SBV b
f) SBV [a]
xs
                           SBV [c] -> ChainsTo (SBV [c]) -> ChainsTo (SBV [c])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV c
g (SBV b -> SBV c) -> (SBV a -> SBV b) -> SBV a -> SBV c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBV a -> SBV b
f) SBV a
x SBV c -> SBV [c] -> SBV [c]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV c) -> SBV [a] -> SBV [c]
forall func a b. SMap func a b => func -> SList a -> SList b
map (SBV b -> SBV c
g (SBV b -> SBV c) -> (SBV a -> SBV b) -> SBV a -> SBV c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBV a -> SBV b
f) SBV [a]
xs
                           SBV [c] -> ChainsTo (SBV [c]) -> ChainsTo (SBV [c])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV c) -> SBV [a] -> SBV [c]
forall func a b. SMap func a b => func -> SList a -> SList b
map (SBV b -> SBV c
g (SBV b -> SBV c) -> (SBV a -> SBV b) -> SBV a -> SBV c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBV a -> SBV b
f) (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                           SBV [c] -> ChainsTo (SBV [c]) -> ChainsTo (SBV [c])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [c])
TPProofRaw (SBV [c])
forall a. TPProofRaw a
qed

-- | @foldr f a . map g == foldr (f . g) a@
--
-- >>> runTP $ foldrMapFusion @String @Bool @Integer (uninterpret "a") (uninterpret "b") (uninterpret "c")
-- Inductive lemma: foldrMapFusion
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] foldrMapFusion :: Ɐxs ∷ [[Char]] → Bool
foldrMapFusion :: forall a b c. (SymVal a, SymVal b, SymVal c) => SBV c -> (SBV a -> SBV b) -> (SBV b -> SBV c -> SBV c) -> TP (Proof (Forall "xs" [a] -> SBool))
foldrMapFusion :: forall a b c.
(SymVal a, SymVal b, SymVal c) =>
SBV c
-> (SBV a -> SBV b)
-> (SBV b -> SBV c -> SBV c)
-> TP (Proof (Forall "xs" [a] -> SBool))
foldrMapFusion SBV c
a SBV a -> SBV b
g SBV b -> SBV c -> SBV c
f =
  String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) c)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"foldrMapFusion"
         (\(Forall SBV [a]
xs) -> (SBV b -> SBV c -> SBV c) -> SBV c -> SList b -> SBV c
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV b -> SBV c -> SBV c
f SBV c
a ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
g SBV [a]
xs) SBV c -> SBV c -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV c -> SBV c) -> SBV c -> SBV [a] -> SBV c
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr (SBV b -> SBV c -> SBV c
f (SBV b -> SBV c -> SBV c)
-> (SBV a -> SBV b) -> SBV a -> SBV c -> SBV c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBV a -> SBV b
g) SBV c
a SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) c)
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) c)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
         \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) -> [] [SBool] -> TPProofRaw (SBV c) -> (SBool, TPProofRaw (SBV c))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV b -> SBV c -> SBV c) -> SBV c -> SList b -> SBV c
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV b -> SBV c -> SBV c
f SBV c
a ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
g (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs))
                           SBV c -> ChainsTo (SBV c) -> ChainsTo (SBV c)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV c -> SBV c) -> SBV c -> SList b -> SBV c
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV b -> SBV c -> SBV c
f SBV c
a (SBV a -> SBV b
g SBV a
x SBV b -> SList b -> SList b
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
g SBV [a]
xs)
                           SBV c -> ChainsTo (SBV c) -> ChainsTo (SBV c)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV b
g SBV a
x SBV b -> SBV c -> SBV c
`f` (SBV b -> SBV c -> SBV c) -> SBV c -> SList b -> SBV c
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV b -> SBV c -> SBV c
f SBV c
a ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
g SBV [a]
xs)
                           SBV c -> Proof SBool -> Hinted (SBV c)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                           TPProofRaw (SBV c)
-> ChainsTo (TPProofRaw (SBV c)) -> ChainsTo (TPProofRaw (SBV c))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV b
g SBV a
x SBV b -> SBV c -> SBV c
`f` (SBV a -> SBV c -> SBV c) -> SBV c -> SBV [a] -> SBV c
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr (SBV b -> SBV c -> SBV c
f (SBV b -> SBV c -> SBV c)
-> (SBV a -> SBV b) -> SBV a -> SBV c -> SBV c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBV a -> SBV b
g) SBV c
a SBV [a]
xs
                           SBV c -> ChainsTo (SBV c) -> ChainsTo (SBV c)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV c -> SBV c) -> SBV c -> SBV [a] -> SBV c
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr (SBV b -> SBV c -> SBV c
f (SBV b -> SBV c -> SBV c)
-> (SBV a -> SBV b) -> SBV a -> SBV c -> SBV c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBV a -> SBV b
g) SBV c
a (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                           SBV c -> ChainsTo (SBV c) -> ChainsTo (SBV c)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV c)
TPProofRaw (SBV c)
forall a. TPProofRaw a
qed

-- |
--
-- @
--   f . foldr g a == foldr h b
--   provided, f a = b and for all x and y, f (g x y) == h x (f y).
-- @
--
-- >>> runTP $ foldrFusion @String @Bool @Integer (uninterpret "a") (uninterpret "b") (uninterpret "f") (uninterpret "g") (uninterpret "h")
-- Inductive lemma: foldrFusion
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] foldrFusion :: Ɐxs ∷ [[Char]] → Bool
foldrFusion :: forall a b c. (SymVal a, SymVal b, SymVal c) => SBV c -> SBV b -> (SBV c -> SBV b) -> (SBV a -> SBV c -> SBV c) -> (SBV a -> SBV b -> SBV b) -> TP (Proof (Forall "xs" [a] -> SBool))
foldrFusion :: forall a b c.
(SymVal a, SymVal b, SymVal c) =>
SBV c
-> SBV b
-> (SBV c -> SBV b)
-> (SBV a -> SBV c -> SBV c)
-> (SBV a -> SBV b -> SBV b)
-> TP (Proof (Forall "xs" [a] -> SBool))
foldrFusion SBV c
a SBV b
b SBV c -> SBV b
f SBV a -> SBV c -> SBV c
g SBV a -> SBV b -> SBV b
h = do
   let -- Assumptions under which the equality holds
       h1 :: SBool
h1 = SBV c -> SBV b
f SBV c
a SBV b -> SBV b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV b
b
       h2 :: SBool
h2 = (Forall Any a -> Forall Any c -> SBool) -> SBool
forall a. QuantifiedBool a => a -> SBool
quantifiedBool ((Forall Any a -> Forall Any c -> SBool) -> SBool)
-> (Forall Any a -> Forall Any c -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \(Forall SBV a
x) (Forall SBV c
y) -> SBV c -> SBV b
f (SBV a -> SBV c -> SBV c
g SBV a
x SBV c
y) SBV b -> SBV b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a -> SBV b -> SBV b
h SBV a
x (SBV c -> SBV b
f SBV c
y)

   String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) b)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"foldrFusion"
          (\(Forall SBV [a]
xs) -> SBool
h1 SBool -> SBool -> SBool
.&& SBool
h2 SBool -> SBool -> SBool
.=> SBV c -> SBV b
f ((SBV a -> SBV c -> SBV c) -> SBV c -> SBV [a] -> SBV c
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV c -> SBV c
g SBV c
a SBV [a]
xs) SBV b -> SBV b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV b -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV b -> SBV b
h SBV b
b SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) b)
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) b)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) -> [Item [SBool]
SBool
h1, Item [SBool]
SBool
h2] [SBool] -> TPProofRaw (SBV b) -> (SBool, TPProofRaw (SBV b))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV c -> SBV b
f ((SBV a -> SBV c -> SBV c) -> SBV c -> SBV [a] -> SBV c
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV c -> SBV c
g SBV c
a (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs))
                                  SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV c -> SBV b
f (SBV a -> SBV c -> SBV c
g SBV a
x ((SBV a -> SBV c -> SBV c) -> SBV c -> SBV [a] -> SBV c
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV c -> SBV c
g SBV c
a SBV [a]
xs))
                                  SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV b -> SBV b
h SBV a
x (SBV c -> SBV b
f ((SBV a -> SBV c -> SBV c) -> SBV c -> SBV [a] -> SBV c
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV c -> SBV c
g SBV c
a SBV [a]
xs))
                                  SBV b -> Proof SBool -> Hinted (SBV b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                                  TPProofRaw (SBV b)
-> ChainsTo (TPProofRaw (SBV b)) -> ChainsTo (TPProofRaw (SBV b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV b -> SBV b
h SBV a
x ((SBV a -> SBV b -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV b -> SBV b
h SBV b
b SBV [a]
xs)
                                  SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV b -> SBV b
h SBV b
b (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                  SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV b)
TPProofRaw (SBV b)
forall a. TPProofRaw a
qed

-- | @foldr f a (xs ++ ys) == foldr f (foldr f a ys) xs@
--
-- >>> runTP $ foldrOverAppend @Integer (uninterpret "a") (uninterpret "f")
-- Inductive lemma: foldrOverAppend
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] foldrOverAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
foldrOverAppend :: forall a. SymVal a => SBV a -> (SBV a -> SBV a -> SBV a) -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
foldrOverAppend :: forall a.
SymVal a =>
SBV a
-> (SBV a -> SBV a -> SBV a)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
foldrOverAppend SBV a
a SBV a -> SBV a -> SBV a
f =
   String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) a)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "ys" [a] -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"foldrOverAppend"
          (\(Forall SBV [a]
xs) (Forall SBV [a]
ys) -> (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys) SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f ((SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a SBV [a]
ys) SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) a)
 -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) a)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) SBV [a]
ys -> [] [SBool] -> TPProofRaw (SBV a) -> (SBool, TPProofRaw (SBV a))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a ((SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys)
                               SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys))
                               SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV a -> SBV a
`f` (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys)
                               SBV a -> Proof (Forall "ys" [a] -> SBool) -> Hinted (SBV a)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
Proof (Forall "ys" [a] -> SBool)
ih
                               TPProofRaw (SBV a)
-> ChainsTo (TPProofRaw (SBV a)) -> ChainsTo (TPProofRaw (SBV a))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV a -> SBV a
`f` (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f ((SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a SBV [a]
ys) SBV [a]
xs
                               SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f ((SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a SBV [a]
ys) (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                               SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV a)
TPProofRaw (SBV a)
forall a. TPProofRaw a
qed

-- | @foldl f e (xs ++ ys) == foldl f (foldl f e xs) ys@
--
-- >>> runTP $ foldlOverAppend @Integer @Bool (uninterpret "f")
-- Inductive lemma: foldlOverAppend
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] foldlOverAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Ɐe ∷ Bool → Bool
foldlOverAppend :: forall a b. (SymVal a, SymVal b) => (SBV b -> SBV a -> SBV b) -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
foldlOverAppend :: forall a b.
(SymVal a, SymVal b) =>
(SBV b -> SBV a -> SBV b)
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
foldlOverAppend SBV b -> SBV a -> SBV b
f =
   String
-> (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool)
-> (Proof
      (IHType
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
    -> IHArg
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool)
    -> IStepArgs
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool) b)
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
forall t.
(Proposition
   (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool)
-> (Proof
      (IHType
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
    -> IHArg
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool)
    -> IStepArgs
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool) t)
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"foldlOverAppend"
          (\(Forall SBV [a]
xs) (Forall SBV [a]
ys) (Forall SBV b
a) -> (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
f SBV b
a (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys) SBV b -> SBV b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
f ((SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
f SBV b
a SBV [a]
xs) SBV [a]
ys) ((Proof
    (IHType
       (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
  -> IHArg
       (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool)
  -> IStepArgs
       (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool) b)
 -> TP
      (Proof
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool)))
-> (Proof
      (IHType
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
    -> IHArg
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool)
    -> IStepArgs
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool) b)
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof
  (IHType
     (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
ih (SBV a
x, SBV [a]
xs) SBV [a]
ys SBV b
a -> [] [SBool] -> TPProofRaw (SBV b) -> (SBool, TPProofRaw (SBV b))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
f SBV b
a ((SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys)
                                 SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
f SBV b
a (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys))
                                 SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
f (SBV b
a SBV b -> SBV a -> SBV b
`f` SBV a
x) (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys)
                                 -- z3 is smart enough to instantiate the IH correctly below, but we're
                                 -- using an explicit instantiation to be clear about the use of @a@ at a different value
                                 SBV b -> Proof Bool -> Hinted (SBV b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (IHType
     (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
Proof (Forall "ys" [a] -> Forall "e" b -> SBool)
ih Proof (Forall "ys" [a] -> Forall "e" b -> SBool)
-> IArgs (Forall "ys" [a] -> Forall "e" b -> SBool) -> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"ys" SBV [a]
ys, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"e" (SBV b
a SBV b -> SBV a -> SBV b
`f` SBV a
x))
                                 TPProofRaw (SBV b)
-> ChainsTo (TPProofRaw (SBV b)) -> ChainsTo (TPProofRaw (SBV b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
f ((SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
f (SBV b
a SBV b -> SBV a -> SBV b
`f` SBV a
x) SBV [a]
xs) SBV [a]
ys
                                 SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV b)
TPProofRaw (SBV b)
forall a. TPProofRaw a
qed

-- | @foldr f e xs == foldl (flip f) e (reverse xs)@
--
-- >>> runTP $ foldrFoldlDuality @Integer @String (uninterpret "f")
-- Inductive lemma: foldlOverAppend
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Result:                               Q.E.D.
-- Inductive lemma: foldrFoldlDuality
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Step: 6                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] foldrFoldlDuality :: Ɐxs ∷ [Integer] → Ɐe ∷ [Char] → Bool
foldrFoldlDuality :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b -> SBV b) -> TP (Proof (Forall "xs" [a] -> Forall "e" b -> SBool))
foldrFoldlDuality :: forall a b.
(SymVal a, SymVal b) =>
(SBV a -> SBV b -> SBV b)
-> TP (Proof (Forall "xs" [a] -> Forall "e" b -> SBool))
foldrFoldlDuality SBV a -> SBV b -> SBV b
f = do
   Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool)
foa <- (SBV b -> SBV a -> SBV b)
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
forall a b.
(SymVal a, SymVal b) =>
(SBV b -> SBV a -> SBV b)
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
foldlOverAppend ((SBV a -> SBV b -> SBV b) -> SBV b -> SBV a -> SBV b
forall a b c. (a -> b -> c) -> b -> a -> c
flip SBV a -> SBV b -> SBV b
f)

   String
-> (Forall "xs" [a] -> Forall "e" b -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "e" b -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "e" b -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "e" b -> SBool) b)
-> TP (Proof (Forall "xs" [a] -> Forall "e" b -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "e" b -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "e" b -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "e" b -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "e" b -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "e" b -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "e" b -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"foldrFoldlDuality"
          (\(Forall SList a
xs) (Forall SBV b
e) -> (SBV a -> SBV b -> SBV b) -> SBV b -> SList a -> SBV b
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV b -> SBV b
f SBV b
e SList a
xs SBV b -> SBV b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV b -> SBV a -> SBV b) -> SBV b -> SList a -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl ((SBV a -> SBV b -> SBV b) -> SBV b -> SBV a -> SBV b
forall a b c. (a -> b -> c) -> b -> a -> c
flip SBV a -> SBV b -> SBV b
f) SBV b
e (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
xs)) ((Proof (IHType (Forall "xs" [a] -> Forall "e" b -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "e" b -> SBool)
  -> IStepArgs (Forall "xs" [a] -> Forall "e" b -> SBool) b)
 -> TP (Proof (Forall "xs" [a] -> Forall "e" b -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> Forall "e" b -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "e" b -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "e" b -> SBool) b)
-> TP (Proof (Forall "xs" [a] -> Forall "e" b -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> Forall "e" b -> SBool))
ih (SBV a
x, SList a
xs) SBV b
e -> [] [SBool] -> TPProofRaw (SBV b) -> (SBool, TPProofRaw (SBV b))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- let ff :: SBV b -> SBV a -> SBV b
ff  = (SBV a -> SBV b -> SBV b) -> SBV b -> SBV a -> SBV b
forall a b c. (a -> b -> c) -> b -> a -> c
flip SBV a -> SBV b -> SBV b
f
                                     rxs :: SList a
rxs = SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
xs
                                 in (SBV a -> SBV b -> SBV b) -> SBV b -> SList a -> SBV b
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV b -> SBV b
f SBV b
e (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs)
                                 SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV b -> SBV b
`f` (SBV a -> SBV b -> SBV b) -> SBV b -> SList a -> SBV b
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV b -> SBV b
f SBV b
e SList a
xs
                                 SBV b -> Proof (Forall "e" b -> SBool) -> Hinted (SBV b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "e" b -> SBool))
Proof (Forall "e" b -> SBool)
ih
                                 TPProofRaw (SBV b)
-> ChainsTo (TPProofRaw (SBV b)) -> ChainsTo (TPProofRaw (SBV b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV b -> SBV b
`f` (SBV b -> SBV a -> SBV b) -> SBV b -> SList a -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
ff SBV b
e SList a
rxs
                                 SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV a -> SBV b) -> SBV b -> SList a -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
ff SBV b
e SList a
rxs SBV b -> SBV a -> SBV b
`ff` SBV a
x
                                 SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV a -> SBV b) -> SBV b -> SList a -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
ff ((SBV b -> SBV a -> SBV b) -> SBV b -> SList a -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
ff SBV b
e SList a
rxs) [Item (SList a)
SBV a
x]
                                 SBV b
-> Proof
     (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool)
-> Hinted (SBV b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool)
foa
                                 TPProofRaw (SBV b)
-> ChainsTo (TPProofRaw (SBV b)) -> ChainsTo (TPProofRaw (SBV b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV a -> SBV b) -> SBV b -> SList a -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
ff SBV b
e (SList a
rxs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ [Item (SList a)
SBV a
x])
                                 SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV a -> SBV b) -> SBV b -> SList a -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
ff SBV b
e (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs))
                                 SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV b)
TPProofRaw (SBV b)
forall a. TPProofRaw a
qed

-- | Given:
--
-- @
--     x \@ (y \@ z) = (x \@ y) \@ z     (associativity of @)
-- and e \@ x = x                     (left unit)
-- and x \@ e = x                     (right unit)
-- @
--
-- Proves:
--
-- @
--     foldr (\@) e xs == foldl (\@) e xs
-- @
--
-- >>> runTP $ foldrFoldlDualityGeneralized @Integer (uninterpret "e") (uninterpret "|@|")
-- Inductive lemma: helper
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- Inductive lemma: foldrFoldlDuality
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Step: 6                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] foldrFoldlDuality :: Ɐxs ∷ [Integer] → Bool
foldrFoldlDualityGeneralized :: forall a. SymVal a => SBV a -> (SBV a -> SBV a -> SBV a) -> TP (Proof (Forall "xs" [a] -> SBool))
foldrFoldlDualityGeneralized :: forall a.
SymVal a =>
SBV a
-> (SBV a -> SBV a -> SBV a)
-> TP (Proof (Forall "xs" [a] -> SBool))
foldrFoldlDualityGeneralized SBV a
e SBV a -> SBV a -> SBV a
(@) = do
   -- Assumptions under which the equality holds
   let assoc :: SBool
assoc = (Forall Any a -> Forall Any a -> Forall Any a -> SBool) -> SBool
forall a. QuantifiedBool a => a -> SBool
quantifiedBool ((Forall Any a -> Forall Any a -> Forall Any a -> SBool) -> SBool)
-> (Forall Any a -> Forall Any a -> Forall Any a -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \(Forall SBV a
x) (Forall SBV a
y) (Forall SBV a
z) -> SBV a
x SBV a -> SBV a -> SBV a
@ (SBV a
y SBV a -> SBV a -> SBV a
@ SBV a
z) SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a
x SBV a -> SBV a -> SBV a
@ SBV a
y) SBV a -> SBV a -> SBV a
@ SBV a
z
       lunit :: SBool
lunit = (Forall Any a -> SBool) -> SBool
forall a. QuantifiedBool a => a -> SBool
quantifiedBool ((Forall Any a -> SBool) -> SBool)
-> (Forall Any a -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \(Forall SBV a
x) -> SBV a
e SBV a -> SBV a -> SBV a
@ SBV a
x SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x
       runit :: SBool
runit = (Forall Any a -> SBool) -> SBool
forall a. QuantifiedBool a => a -> SBool
quantifiedBool ((Forall Any a -> SBool) -> SBool)
-> (Forall Any a -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \(Forall SBV a
x) -> SBV a
x SBV a -> SBV a -> SBV a
@ SBV a
e SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x

   -- Helper: foldl (@) (y @ z) xs = y @ foldl (@) z xs
   -- Note the instantiation of the IH at a different value for z. It turns out
   -- we don't have to actually specify this since z3 can figure it out by itself, but we're being explicit.
   Proof (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool)
helper <- String
-> (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool)
-> (Proof
      (IHType (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool)
    -> IStepArgs
         (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool) a)
-> TP
     (Proof (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool))
forall t.
(Proposition
   (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool)
-> (Proof
      (IHType (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool)
    -> IStepArgs
         (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool) t)
-> TP
     (Proof (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"helper"
                    (\(Forall @"xs" SBV [a]
xs) (Forall @"y" SBV a
y) (Forall @"z" SBV a
z) -> SBool
assoc SBool -> SBool -> SBool
.=> (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV a -> SBV a -> SBV a
(@) (SBV a
y SBV a -> SBV a -> SBV a
@ SBV a
z) SBV [a]
xs SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
y SBV a -> SBV a -> SBV a
@ (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV a -> SBV a -> SBV a
(@) SBV a
z SBV [a]
xs) ((Proof
    (IHType (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool)
  -> IStepArgs
       (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool) a)
 -> TP
      (Proof (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool)))
-> (Proof
      (IHType (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool)
    -> IStepArgs
         (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool) a)
-> TP
     (Proof (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool))
forall a b. (a -> b) -> a -> b
$
                    \Proof
  (IHType (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool))
ih (SBV a
x, SBV [a]
xs) SBV a
y SBV a
z -> [Item [SBool]
SBool
assoc] [SBool] -> TPProofRaw (SBV a) -> (SBool, TPProofRaw (SBV a))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV a -> SBV a -> SBV a
(@) (SBV a
y SBV a -> SBV a -> SBV a
@ SBV a
z) (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                               SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV a -> SBV a -> SBV a
(@) ((SBV a
y SBV a -> SBV a -> SBV a
@ SBV a
z) SBV a -> SBV a -> SBV a
@ SBV a
x) SBV [a]
xs
                                               SBV a -> SBool -> Hinted (SBV a)
forall a b. HintsTo a b => a -> b -> Hinted a
?? SBool
assoc
                                               TPProofRaw (SBV a)
-> ChainsTo (TPProofRaw (SBV a)) -> ChainsTo (TPProofRaw (SBV a))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV a -> SBV a -> SBV a
(@) (SBV a
y SBV a -> SBV a -> SBV a
@ (SBV a
z SBV a -> SBV a -> SBV a
@ SBV a
x)) SBV [a]
xs
                                               SBV a -> Proof Bool -> Hinted (SBV a)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (IHType (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool))
Proof (Forall "y" a -> Forall "z" a -> SBool)
ih Proof (Forall "y" a -> Forall "z" a -> SBool)
-> IArgs (Forall "y" a -> Forall "z" a -> SBool) -> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"y" SBV a
y, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"z" (SBV a
z SBV a -> SBV a -> SBV a
@ SBV a
x))
                                               TPProofRaw (SBV a)
-> ChainsTo (TPProofRaw (SBV a)) -> ChainsTo (TPProofRaw (SBV a))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
y SBV a -> SBV a -> SBV a
@ (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV a -> SBV a -> SBV a
(@) (SBV a
z SBV a -> SBV a -> SBV a
@ SBV a
x) SBV [a]
xs
                                               SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
y SBV a -> SBV a -> SBV a
@ (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV a -> SBV a -> SBV a
(@) SBV a
z (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                               SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV a)
TPProofRaw (SBV a)
forall a. TPProofRaw a
qed

   String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) a)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"foldrFoldlDuality"
          (\(Forall SBV [a]
xs) -> SBool
assoc SBool -> SBool -> SBool
.&& SBool
lunit SBool -> SBool -> SBool
.&& SBool
runit SBool -> SBool -> SBool
.=> (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
(@) SBV a
e SBV [a]
xs SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV a -> SBV a -> SBV a
(@) SBV a
e SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) a)
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) a)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) -> [Item [SBool]
SBool
assoc, Item [SBool]
SBool
lunit, Item [SBool]
SBool
runit] [SBool] -> TPProofRaw (SBV a) -> (SBool, TPProofRaw (SBV a))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
(@) SBV a
e (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                               SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV a -> SBV a
@ (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
(@) SBV a
e SBV [a]
xs
                                               SBV a -> Proof SBool -> Hinted (SBV a)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                                               TPProofRaw (SBV a)
-> ChainsTo (TPProofRaw (SBV a)) -> ChainsTo (TPProofRaw (SBV a))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV a -> SBV a
@ (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV a -> SBV a -> SBV a
(@) SBV a
e SBV [a]
xs
                                               SBV a
-> Proof (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool)
-> Hinted (SBV a)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "y" a -> Forall "z" a -> SBool)
helper
                                               TPProofRaw (SBV a)
-> ChainsTo (TPProofRaw (SBV a)) -> ChainsTo (TPProofRaw (SBV a))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV a -> SBV a -> SBV a
(@) (SBV a
x SBV a -> SBV a -> SBV a
@ SBV a
e) SBV [a]
xs
                                               SBV a -> SBool -> Hinted (SBV a)
forall a b. HintsTo a b => a -> b -> Hinted a
?? SBool
runit
                                               TPProofRaw (SBV a)
-> ChainsTo (TPProofRaw (SBV a)) -> ChainsTo (TPProofRaw (SBV a))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV a -> SBV a -> SBV a
(@) SBV a
x SBV [a]
xs
                                               SBV a -> SBool -> Hinted (SBV a)
forall a b. HintsTo a b => a -> b -> Hinted a
?? SBool
lunit
                                               TPProofRaw (SBV a)
-> ChainsTo (TPProofRaw (SBV a)) -> ChainsTo (TPProofRaw (SBV a))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV a -> SBV a -> SBV a
(@) (SBV a
e SBV a -> SBV a -> SBV a
@ SBV a
x) SBV [a]
xs
                                               SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SBV [a] -> SBV a
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV a -> SBV a -> SBV a
(@) SBV a
e (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                               SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV a)
TPProofRaw (SBV a)
forall a. TPProofRaw a
qed

-- | Given:
--
-- @
--        (x \<+> y) \<*> z = x \<+> (y \<*> z)
--   and  x \<+> e = e \<*> x
-- @
--
-- Proves:
--
-- @
--    foldr (\<+>) e xs = foldl (\<*>) e xs
-- @
--
-- In Bird's Introduction to Functional Programming book (2nd edition) this is called the second duality theorem:
--
-- >>> runTP $ foldrFoldl @Integer @String (uninterpret "<+>") (uninterpret "<*>") (uninterpret "e")
-- Inductive lemma: foldl over <*>/<+>
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- Inductive lemma: foldrFoldl
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] foldrFoldl :: Ɐxs ∷ [Integer] → Bool
foldrFoldl :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b -> SBV b) -> (SBV b -> SBV a -> SBV b) -> SBV b -> TP (Proof (Forall "xs" [a] -> SBool))
foldrFoldl :: forall a b.
(SymVal a, SymVal b) =>
(SBV a -> SBV b -> SBV b)
-> (SBV b -> SBV a -> SBV b)
-> SBV b
-> TP (Proof (Forall "xs" [a] -> SBool))
foldrFoldl SBV a -> SBV b -> SBV b
(<+>) SBV b -> SBV a -> SBV b
(<*>) SBV b
e = do
   -- Assumptions about the operators
   let -- (x <+> y) <*> z == x <+> (y <*> z)
       assoc :: SBool
assoc = (Forall Any a -> Forall Any b -> Forall Any a -> SBool) -> SBool
forall a. QuantifiedBool a => a -> SBool
quantifiedBool ((Forall Any a -> Forall Any b -> Forall Any a -> SBool) -> SBool)
-> (Forall Any a -> Forall Any b -> Forall Any a -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \(Forall SBV a
x) (Forall SBV b
y) (Forall SBV a
z) -> (SBV a
x SBV a -> SBV b -> SBV b
<+> SBV b
y) SBV b -> SBV a -> SBV b
<*> SBV a
z SBV b -> SBV b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x SBV a -> SBV b -> SBV b
<+> (SBV b
y SBV b -> SBV a -> SBV b
<*> SBV a
z)

       -- x <+> e == e <*> x
       unit :: SBool
unit  = (Forall Any a -> SBool) -> SBool
forall a. QuantifiedBool a => a -> SBool
quantifiedBool ((Forall Any a -> SBool) -> SBool)
-> (Forall Any a -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \(Forall SBV a
x) -> SBV a
x SBV a -> SBV b -> SBV b
<+> SBV b
e SBV b -> SBV b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV b
e SBV b -> SBV a -> SBV b
<*> SBV a
x

   -- Helper: x <+> foldl (<*>) y xs == foldl (<*>) (x <+> y) xs
   Proof (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool)
helper <-
      String
-> (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool)
-> (Proof
      (IHType (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool)
    -> IStepArgs
         (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool) b)
-> TP
     (Proof (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool))
forall t.
(Proposition
   (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool)
-> (Proof
      (IHType (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool)
    -> IStepArgs
         (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool) t)
-> TP
     (Proof (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"foldl over <*>/<+>"
             (\(Forall @"xs" SBV [a]
xs) (Forall @"x" SBV a
x) (Forall @"y" SBV b
y) -> SBool
assoc SBool -> SBool -> SBool
.=> SBV a
x SBV a -> SBV b -> SBV b
<+> (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
(<*>) SBV b
y SBV [a]
xs SBV b -> SBV b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
(<*>) (SBV a
x SBV a -> SBV b -> SBV b
<+> SBV b
y) SBV [a]
xs) ((Proof
    (IHType (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool)
  -> IStepArgs
       (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool) b)
 -> TP
      (Proof (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool)))
-> (Proof
      (IHType (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool)
    -> IStepArgs
         (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool) b)
-> TP
     (Proof (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool))
forall a b. (a -> b) -> a -> b
$

             -- Using z to avoid confusion with the variable x already present, following Bird.
             -- z3 can figure out the proper instantiation of ih so the at call is unnecessary, but being explicit is helpful.
             \Proof
  (IHType (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool))
ih (SBV a
z, SBV [a]
xs) SBV a
x SBV b
y -> [Item [SBool]
SBool
assoc] [SBool] -> TPProofRaw (SBV b) -> (SBool, TPProofRaw (SBV b))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV a
x SBV a -> SBV b -> SBV b
<+> (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
(<*>) SBV b
y (SBV a
z SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                        SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV b -> SBV b
<+> (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
(<*>) (SBV b
y SBV b -> SBV a -> SBV b
<*> SBV a
z) SBV [a]
xs
                                        SBV b -> Proof Bool -> Hinted (SBV b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (IHType (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool))
Proof (Forall "x" a -> Forall "y" b -> SBool)
ih Proof (Forall "x" a -> Forall "y" b -> SBool)
-> IArgs (Forall "x" a -> Forall "y" b -> SBool) -> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"x" SBV a
x, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"y" (SBV b
y SBV b -> SBV a -> SBV b
<*> SBV a
z))
                                        TPProofRaw (SBV b)
-> ChainsTo (TPProofRaw (SBV b)) -> ChainsTo (TPProofRaw (SBV b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
(<*>) (SBV a
x SBV a -> SBV b -> SBV b
<+> (SBV b
y SBV b -> SBV a -> SBV b
<*> SBV a
z)) SBV [a]
xs
                                        SBV b -> SBool -> Hinted (SBV b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? SBool
assoc
                                        TPProofRaw (SBV b)
-> ChainsTo (TPProofRaw (SBV b)) -> ChainsTo (TPProofRaw (SBV b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
(<*>) ((SBV a
x SBV a -> SBV b -> SBV b
<+> SBV b
y) SBV b -> SBV a -> SBV b
<*> SBV a
z) SBV [a]
xs
                                        SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
(<*>) (SBV a
x SBV a -> SBV b -> SBV b
<+> SBV b
y) (SBV a
z SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                        SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV b)
TPProofRaw (SBV b)
forall a. TPProofRaw a
qed

   -- Final proof:
   String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) b)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"foldrFoldl"
          (\(Forall SBV [a]
xs) -> SBool
assoc SBool -> SBool -> SBool
.&& SBool
unit SBool -> SBool -> SBool
.=> (SBV a -> SBV b -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV b -> SBV b
(<+>) SBV b
e SBV [a]
xs SBV b -> SBV b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
(<*>) SBV b
e SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) b)
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) b)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) -> [Item [SBool]
SBool
assoc, Item [SBool]
SBool
unit] [SBool] -> TPProofRaw (SBV b) -> (SBool, TPProofRaw (SBV b))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a -> SBV b -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV b -> SBV b
(<+>) SBV b
e (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                       SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV b -> SBV b
<+> (SBV a -> SBV b -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV b -> SBV b
(<+>) SBV b
e SBV [a]
xs
                                       SBV b -> Proof SBool -> Hinted (SBV b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                                       TPProofRaw (SBV b)
-> ChainsTo (TPProofRaw (SBV b)) -> ChainsTo (TPProofRaw (SBV b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV b -> SBV b
<+> (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
(<*>) SBV b
e SBV [a]
xs
                                       SBV b
-> Proof (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool)
-> Hinted (SBV b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "x" a -> Forall "y" b -> SBool)
helper
                                       TPProofRaw (SBV b)
-> ChainsTo (TPProofRaw (SBV b)) -> ChainsTo (TPProofRaw (SBV b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
(<*>) (SBV a
x SBV a -> SBV b -> SBV b
<+> SBV b
e) SBV [a]
xs
                                       SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
(<*>) (SBV b
e SBV b -> SBV a -> SBV b
<*> SBV a
x) SBV [a]
xs
                                       SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV b -> SBV a -> SBV b) -> SBV b -> SBV [a] -> SBV b
forall func a b.
(SFoldL func a b, SymVal a, SymVal b) =>
func -> SBV b -> SList a -> SBV b
foldl SBV b -> SBV a -> SBV b
(<*>) SBV b
e (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                       SBV b -> ChainsTo (SBV b) -> ChainsTo (SBV b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV b)
TPProofRaw (SBV b)
forall a. TPProofRaw a
qed

-- | Provided @f@ is associative and @a@ is its both left and right-unit:
--
-- @foldr f a . concat == foldr f a . map (foldr f a)@
--
-- >>> runTP $ bookKeeping @Integer (uninterpret "a") (uninterpret "f")
-- Inductive lemma: foldBase
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- Inductive lemma: foldrOverAppend
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- Inductive lemma: bookKeeping
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Step: 6                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] bookKeeping :: Ɐxss ∷ [[Integer]] → Bool
--
-- NB. This theorem does not hold if @f@ does not have a left-unit! Consider the input @[[], [x]]@. Left hand side reduces to
-- @x@, while the right hand side reduces to: @f a x@. And unless @f@ is commutative or @a@ is not also a left-unit,
-- then one can find a counter-example. (Aside: if both left and right units exist for a binary operator, then they
-- are necessarily the same element, since @l = f l r = r@. So, an equivalent statement could simply say @f@ has
-- both left and right units.) A concrete counter-example is:
--
-- @
--   data T = A | B | C
--
--   f :: T -> T -> T
--   f C A = A
--   f C B = A
--   f x _ = x
-- @
--
-- You can verify @f@ is associative. Also note that @C@ is the right-unit for @f@, but it isn't the left-unit.
-- In fact, @f@ has no-left unit by the above argument. In this case, the bookkeeping law produces @B@ for
-- the left-hand-side, and @A@ for the right-hand-side for the input @[[], [B]]@.
bookKeeping :: forall a. SymVal a => SBV a -> (SBV a -> SBV a -> SBV a) -> TP (Proof (Forall "xss" [[a]] -> SBool))
bookKeeping :: forall a.
SymVal a =>
SBV a
-> (SBV a -> SBV a -> SBV a)
-> TP (Proof (Forall "xss" [[a]] -> SBool))
bookKeeping SBV a
a SBV a -> SBV a -> SBV a
f = do

   -- Assumptions about f
   let assoc :: SBool
assoc = (Forall Any a -> Forall Any a -> Forall Any a -> SBool) -> SBool
forall a. QuantifiedBool a => a -> SBool
quantifiedBool ((Forall Any a -> Forall Any a -> Forall Any a -> SBool) -> SBool)
-> (Forall Any a -> Forall Any a -> Forall Any a -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \(Forall SBV a
x) (Forall SBV a
y) (Forall SBV a
z) -> SBV a
x SBV a -> SBV a -> SBV a
`f` (SBV a
y SBV a -> SBV a -> SBV a
`f` SBV a
z) SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a
x SBV a -> SBV a -> SBV a
`f` SBV a
y) SBV a -> SBV a -> SBV a
`f` SBV a
z
       rUnit :: SBool
rUnit = (Forall Any a -> SBool) -> SBool
forall a. QuantifiedBool a => a -> SBool
quantifiedBool ((Forall Any a -> SBool) -> SBool)
-> (Forall Any a -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \(Forall SBV a
x) -> SBV a
x SBV a -> SBV a -> SBV a
`f` SBV a
a SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x
       lUnit :: SBool
lUnit = (Forall Any a -> SBool) -> SBool
forall a. QuantifiedBool a => a -> SBool
quantifiedBool ((Forall Any a -> SBool) -> SBool)
-> (Forall Any a -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \(Forall SBV a
x) -> SBV a
a SBV a -> SBV a -> SBV a
`f` SBV a
x SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x

   -- Helper: @foldr f y xs = foldr f a xs `f` y@
   Proof (Forall "xs" [a] -> Forall "y" a -> SBool)
helper <- String
-> (Forall "xs" [a] -> Forall "y" a -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "y" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "y" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "y" a -> SBool) a)
-> TP (Proof (Forall "xs" [a] -> Forall "y" a -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "y" a -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "y" a -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "y" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "y" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "y" a -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "y" a -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"foldBase"
                    (\(Forall SList a
xs) (Forall SBV a
y) -> SBool
lUnit SBool -> SBool -> SBool
.&& SBool
assoc SBool -> SBool -> SBool
.=> (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
y SList a
xs SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a SList a
xs SBV a -> SBV a -> SBV a
`f` SBV a
y) ((Proof (IHType (Forall "xs" [a] -> Forall "y" a -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "y" a -> SBool)
  -> IStepArgs (Forall "xs" [a] -> Forall "y" a -> SBool) a)
 -> TP (Proof (Forall "xs" [a] -> Forall "y" a -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> Forall "y" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "y" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "y" a -> SBool) a)
-> TP (Proof (Forall "xs" [a] -> Forall "y" a -> SBool))
forall a b. (a -> b) -> a -> b
$
                    \Proof (IHType (Forall "xs" [a] -> Forall "y" a -> SBool))
ih (SBV a
x, SList a
xs) SBV a
y -> [Item [SBool]
SBool
lUnit, Item [SBool]
SBool
assoc] [SBool] -> TPProofRaw (SBV a) -> (SBool, TPProofRaw (SBV a))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
y (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs)
                                                    SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV a -> SBV a
`f` (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
y SList a
xs
                                                    SBV a -> Proof (Forall "y" a -> SBool) -> Hinted (SBV a)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "y" a -> SBool))
Proof (Forall "y" a -> SBool)
ih
                                                    TPProofRaw (SBV a)
-> ChainsTo (TPProofRaw (SBV a)) -> ChainsTo (TPProofRaw (SBV a))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV a -> SBV a
`f` ((SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a SList a
xs SBV a -> SBV a -> SBV a
`f` SBV a
y)
                                                    SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a
x SBV a -> SBV a -> SBV a
`f` (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a SList a
xs) SBV a -> SBV a -> SBV a
`f` SBV a
y
                                                    SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs) SBV a -> SBV a -> SBV a
`f` SBV a
y
                                                    SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV a)
TPProofRaw (SBV a)
forall a. TPProofRaw a
qed

   Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
foa <- SBV a
-> (SBV a -> SBV a -> SBV a)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a.
SymVal a =>
SBV a
-> (SBV a -> SBV a -> SBV a)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
foldrOverAppend SBV a
a SBV a -> SBV a -> SBV a
f

   String
-> (Forall "xss" [[a]] -> SBool)
-> (Proof (IHType (Forall "xss" [[a]] -> SBool))
    -> IHArg (Forall "xss" [[a]] -> SBool)
    -> IStepArgs (Forall "xss" [[a]] -> SBool) a)
-> TP (Proof (Forall "xss" [[a]] -> SBool))
forall t.
(Proposition (Forall "xss" [[a]] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xss" [[a]] -> SBool)
-> (Proof (IHType (Forall "xss" [[a]] -> SBool))
    -> IHArg (Forall "xss" [[a]] -> SBool)
    -> IStepArgs (Forall "xss" [[a]] -> SBool) t)
-> TP (Proof (Forall "xss" [[a]] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"bookKeeping"
          (\(Forall SBV [[a]]
xss) -> SBool
assoc SBool -> SBool -> SBool
.&& SBool
rUnit SBool -> SBool -> SBool
.&& SBool
lUnit SBool -> SBool -> SBool
.=> (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a (SBV [[a]] -> SList a
forall a. SymVal a => SList [a] -> SList a
concat SBV [[a]]
xss) SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a ((SList a -> SBV a) -> SBV [[a]] -> SList a
forall func a b. SMap func a b => func -> SList a -> SList b
map ((SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a) SBV [[a]]
xss)) ((Proof (IHType (Forall "xss" [[a]] -> SBool))
  -> IHArg (Forall "xss" [[a]] -> SBool)
  -> IStepArgs (Forall "xss" [[a]] -> SBool) a)
 -> TP (Proof (Forall "xss" [[a]] -> SBool)))
-> (Proof (IHType (Forall "xss" [[a]] -> SBool))
    -> IHArg (Forall "xss" [[a]] -> SBool)
    -> IStepArgs (Forall "xss" [[a]] -> SBool) a)
-> TP (Proof (Forall "xss" [[a]] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xss" [[a]] -> SBool))
ih (SList a
xs, SBV [[a]]
xss) -> [Item [SBool]
SBool
assoc, Item [SBool]
SBool
rUnit, Item [SBool]
SBool
lUnit] [SBool] -> TPProofRaw (SBV a) -> (SBool, TPProofRaw (SBV a))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a (SBV [[a]] -> SList a
forall a. SymVal a => SList [a] -> SList a
concat (SList a
xs SList a -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [[a]]
xss))
                                                 SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a (SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [[a]] -> SList a
forall a. SymVal a => SList [a] -> SList a
concat SBV [[a]]
xss)
                                                 SBV a
-> Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> Hinted (SBV a)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
foa
                                                 TPProofRaw (SBV a)
-> ChainsTo (TPProofRaw (SBV a)) -> ChainsTo (TPProofRaw (SBV a))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f ((SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a (SBV [[a]] -> SList a
forall a. SymVal a => SList [a] -> SList a
concat SBV [[a]]
xss)) SList a
xs
                                                 SBV a -> Proof SBool -> Hinted (SBV a)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xss" [[a]] -> SBool))
ih
                                                 TPProofRaw (SBV a)
-> ChainsTo (TPProofRaw (SBV a)) -> ChainsTo (TPProofRaw (SBV a))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f ((SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a ((SList a -> SBV a) -> SBV [[a]] -> SList a
forall func a b. SMap func a b => func -> SList a -> SList b
map ((SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a) SBV [[a]]
xss)) SList a
xs
                                                 SBV a -> Proof Bool -> Hinted (SBV a)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "y" a -> SBool)
helper Proof (Forall "xs" [a] -> Forall "y" a -> SBool)
-> IArgs (Forall "xs" [a] -> Forall "y" a -> SBool) -> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"xs" SList a
xs, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"y" ((SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a ((SList a -> SBV a) -> SBV [[a]] -> SList a
forall func a b. SMap func a b => func -> SList a -> SList b
map ((SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a) SBV [[a]]
xss)))
                                                 TPProofRaw (SBV a)
-> ChainsTo (TPProofRaw (SBV a)) -> ChainsTo (TPProofRaw (SBV a))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a SList a
xs SBV a -> SBV a -> SBV a
`f` (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a ((SList a -> SBV a) -> SBV [[a]] -> SList a
forall func a b. SMap func a b => func -> SList a -> SList b
map ((SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a) SBV [[a]]
xss)
                                                 SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a ((SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a SList a
xs SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SList a -> SBV a) -> SBV [[a]] -> SList a
forall func a b. SMap func a b => func -> SList a -> SList b
map ((SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a) SBV [[a]]
xss)
                                                 SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a ((SList a -> SBV a) -> SBV [[a]] -> SList a
forall func a b. SMap func a b => func -> SList a -> SList b
map ((SBV a -> SBV a -> SBV a) -> SBV a -> SList a -> SBV a
forall func a b.
SFoldR func a b =>
func -> SBV b -> SList a -> SBV b
foldr SBV a -> SBV a -> SBV a
f SBV a
a) (SList a
xs SList a -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [[a]]
xss))
                                                 SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV a)
TPProofRaw (SBV a)
forall a. TPProofRaw a
qed

-- | @filter p (xs ++ ys) == filter p xs ++ filter p ys@
--
-- >>> runTP $ filterAppend @Integer (uninterpret "p")
-- Inductive lemma: filterAppend
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] filterAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
filterAppend :: forall a. SymVal a => (SBV a -> SBool) -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
filterAppend :: forall a.
SymVal a =>
(SBV a -> SBool)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
filterAppend SBV a -> SBool
p =
   String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "ys" [a] -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"filterAppend"
          (\(Forall SBV [a]
xs) (Forall SBV [a]
ys) -> (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p SBV [a]
ys SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys)) ((Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) [a])
 -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) SBV [a]
ys -> [] [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p SBV [a]
ys
                               SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBV [a] -> SBV [a] -> SBV [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a -> SBool
p SBV a
x) (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p SBV [a]
xs) ((SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p SBV [a]
xs) SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p SBV [a]
ys
                               SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBV [a] -> SBV [a] -> SBV [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a -> SBool
p SBV a
x) (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p SBV [a]
ys) ((SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p SBV [a]
ys)
                               SBV [a] -> Proof (Forall "ys" [a] -> SBool) -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
Proof (Forall "ys" [a] -> SBool)
ih
                               TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBV [a] -> SBV [a] -> SBV [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a -> SBool
p SBV a
x) (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys)) ((SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys))
                               SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys))
                               SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p ((SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys)
                               SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed

-- | @filter p (concat xss) == concatMap (filter p xss)@
--
-- >>> runTP $ filterConcat @Integer (uninterpret "f")
-- Inductive lemma: filterAppend
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Result:                               Q.E.D.
-- Inductive lemma: filterConcat
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] filterConcat :: Ɐxss ∷ [[Integer]] → Bool
filterConcat :: forall a. SymVal a => (SBV a -> SBool) -> TP (Proof (Forall "xss" [[a]] -> SBool))
filterConcat :: forall a.
SymVal a =>
(SBV a -> SBool) -> TP (Proof (Forall "xss" [[a]] -> SBool))
filterConcat SBV a -> SBool
p = do
  Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
fa <- (SBV a -> SBool)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a.
SymVal a =>
(SBV a -> SBool)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
filterAppend SBV a -> SBool
p

  SMTConfig
-> String
-> (Forall "xss" [[a]] -> SBool)
-> (Proof (IHType (Forall "xss" [[a]] -> SBool))
    -> IHArg (Forall "xss" [[a]] -> SBool)
    -> IStepArgs (Forall "xss" [[a]] -> SBool) [a])
-> TP (Proof (Forall "xss" [[a]] -> SBool))
forall t.
(Proposition (Forall "xss" [[a]] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
SMTConfig
-> String
-> (Forall "xss" [[a]] -> SBool)
-> (Proof (IHType (Forall "xss" [[a]] -> SBool))
    -> IHArg (Forall "xss" [[a]] -> SBool)
    -> IStepArgs (Forall "xss" [[a]] -> SBool) t)
-> TP (Proof (Forall "xss" [[a]] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
SMTConfig
-> String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
inductWith SMTConfig
cvc5 String
"filterConcat"
         (\(Forall SBV [[a]]
xss) -> (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p (SBV [[a]] -> SBV [a]
forall a. SymVal a => SList [a] -> SList a
concat SBV [[a]]
xss) SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV [a] -> SBV [a]) -> SBV [[a]] -> SBV [a]
forall func a b.
(SMap func a [b], SymVal b) =>
func -> SList a -> SList b
concatMap ((SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p) SBV [[a]]
xss) ((Proof (IHType (Forall "xss" [[a]] -> SBool))
  -> IHArg (Forall "xss" [[a]] -> SBool)
  -> IStepArgs (Forall "xss" [[a]] -> SBool) [a])
 -> TP (Proof (Forall "xss" [[a]] -> SBool)))
-> (Proof (IHType (Forall "xss" [[a]] -> SBool))
    -> IHArg (Forall "xss" [[a]] -> SBool)
    -> IStepArgs (Forall "xss" [[a]] -> SBool) [a])
-> TP (Proof (Forall "xss" [[a]] -> SBool))
forall a b. (a -> b) -> a -> b
$
         \Proof (IHType (Forall "xss" [[a]] -> SBool))
ih (SBV [a]
xs, SBV [[a]]
xss) -> [] [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p (SBV [[a]] -> SBV [a]
forall a. SymVal a => SList [a] -> SList a
concat (SBV [a]
xs SBV [a] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [[a]]
xss))
                             SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [[a]] -> SBV [a]
forall a. SymVal a => SList [a] -> SList a
concat SBV [[a]]
xss)
                             SBV [a]
-> Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
fa
                             TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p (SBV [[a]] -> SBV [a]
forall a. SymVal a => SList [a] -> SList a
concat SBV [[a]]
xss)
                             SBV [a] -> Proof SBool -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xss" [[a]] -> SBool))
ih
                             TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV [a] -> SBV [a]) -> SBV [[a]] -> SBV [a]
forall func a b.
(SMap func a [b], SymVal b) =>
func -> SList a -> SList b
concatMap ((SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
p) (SBV [a]
xs SBV [a] -> SBV [[a]] -> SBV [[a]]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [[a]]
xss)
                             SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed

-- | @takeWhile f xs ++ dropWhile f xs == xs@
--
-- >>> runTP $ takeDropWhile @Integer (uninterpret "f")
-- Inductive lemma: takeDropWhile
--   Step: Base                            Q.E.D.
--   Step: 1 (2 way case split)
--     Step: 1.1.1                         Q.E.D.
--     Step: 1.1.2                         Q.E.D.
--     Step: 1.2.1                         Q.E.D.
--     Step: 1.2.2                         Q.E.D.
--     Step: 1.Completeness                Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] takeDropWhile :: Ɐxs ∷ [Integer] → Bool
takeDropWhile :: forall a. SymVal a => (SBV a -> SBool) -> TP (Proof (Forall "xs" [a] -> SBool))
takeDropWhile :: forall a.
SymVal a =>
(SBV a -> SBool) -> TP (Proof (Forall "xs" [a] -> SBool))
takeDropWhile SBV a -> SBool
f =
   String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"takeDropWhile"
          (\(Forall SBV [a]
xs) -> (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
takeWhile SBV a -> SBool
f SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
dropWhile SBV a -> SBool
f SBV [a]
xs SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) [a])
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) -> [] [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
takeWhile SBV a -> SBool
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
dropWhile SBV a -> SBool
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBool, TPProofRaw (SBV [a]))] -> TPProofRaw (SBV [a])
forall a. [(SBool, TPProofRaw a)] -> TPProofRaw a
cases [ SBV a -> SBool
f SBV a
x        SBool -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
takeWhile SBV a -> SBool
f SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
dropWhile SBV a -> SBool
f SBV [a]
xs
                                                   SBV [a] -> Proof SBool -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                                                   TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs
                                                   SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed
                                     , SBool -> SBool
sNot (SBV a -> SBool
f SBV a
x) SBool -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> [] SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs
                                                   SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs
                                                   SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed
                                     ]
-- | Remove adjacent duplicates.
destutter :: SymVal a => SList a -> SList a
destutter :: forall a. SymVal a => SList a -> SList a
destutter = String -> (SList a -> SList a) -> SList a -> SList a
forall a.
(SMTDefinable a, Typeable a, Lambda Symbolic a) =>
String -> a -> a
smtFunction String
"destutter" ((SList a -> SList a) -> SList a -> SList a)
-> (SList a -> SList a) -> SList a -> SList a
forall a b. (a -> b) -> a -> b
$ \SList a
xs -> SBool -> SList a -> SList a -> SList a
forall a. Mergeable a => SBool -> a -> a -> a
ite (SList a -> SBool
forall a. SymVal a => SList a -> SBool
null SList a
xs SBool -> SBool -> SBool
.|| SList a -> SBool
forall a. SymVal a => SList a -> SBool
null (SList a -> SList a
forall a. SymVal a => SList a -> SList a
tail SList a
xs))
                                                 SList a
xs
                                                 (let (SBV a
a, SList a
as) = SList a -> (SBV a, SList a)
forall a. SymVal a => SList a -> (SBV a, SList a)
uncons SList a
xs
                                                      r :: SList a
r       = SList a -> SList a
forall a. SymVal a => SList a -> SList a
destutter SList a
as
                                                  in SBool -> SList a -> SList a -> SList a
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a
a SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SList a -> SBV a
forall a. SymVal a => SList a -> SBV a
head SList a
as) SList a
r (SBV a
a SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
r))

-- | @destutter (destutter xs) == destutter xs@
--
-- >>> runTP $ destutterIdempotent @Integer
-- Inductive lemma: helper1
--   Step: Base                            Q.E.D.
--   Step: 1 (2 way case split)
--     Step: 1.1                           Q.E.D.
--     Step: 1.2.1                         Q.E.D.
--     Step: 1.2.2                         Q.E.D.
--     Step: 1.Completeness                Q.E.D.
--   Result:                               Q.E.D.
-- Inductive lemma: helper2
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Result:                               Q.E.D.
-- Inductive lemma (strong): helper3
--   Step: Measure is non-negative         Q.E.D.
--   Step: 1 (2 way full case split)
--     Step: 1.1                           Q.E.D.
--     Step: 1.2 (2 way full case split)
--       Step: 1.2.1                       Q.E.D.
--       Step: 1.2.2.1                     Q.E.D.
--       Step: 1.2.2.2 (2 way case split)
--         Step: 1.2.2.2.1.1               Q.E.D.
--         Step: 1.2.2.2.1.2               Q.E.D.
--         Step: 1.2.2.2.2.1               Q.E.D.
--         Step: 1.2.2.2.2.2               Q.E.D.
--         Step: 1.2.2.2.Completeness      Q.E.D.
--   Result:                               Q.E.D.
-- Lemma: destutterIdempotent              Q.E.D.
-- [Proven] destutterIdempotent :: Ɐxs ∷ [Integer] → Bool
destutterIdempotent :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
destutterIdempotent :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
destutterIdempotent = do

   -- No adjacent duplicates
   let noAdd :: SBV [a] -> SBool
noAdd = String -> (SBV [a] -> SBool) -> SBV [a] -> SBool
forall a.
(SMTDefinable a, Typeable a, Lambda Symbolic a) =>
String -> a -> a
smtFunction String
"noAdd" ((SBV [a] -> SBool) -> SBV [a] -> SBool)
-> (SBV [a] -> SBool) -> SBV [a] -> SBool
forall a b. (a -> b) -> a -> b
$ \SBV [a]
xs -> SBV [a] -> SBool
forall a. SymVal a => SList a -> SBool
null SBV [a]
xs SBool -> SBool -> SBool
.|| SBV [a] -> SBool
forall a. SymVal a => SList a -> SBool
null (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
tail SBV [a]
xs) SBool -> SBool -> SBool
.|| (SBV [a] -> SBV a
forall a. SymVal a => SList a -> SBV a
head SBV [a]
xs SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
./= SBV [a] -> SBV a
forall a. SymVal a => SList a -> SBV a
head (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
tail SBV [a]
xs) SBool -> SBool -> SBool
.&& SBV [a] -> SBool
noAdd (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
tail SBV [a]
xs))

   -- Helper: The head of a destuttered non-empty list does not change
   Proof (Forall "xs" [a] -> Forall "h" a -> SBool)
helper1 <- String
-> (Forall "xs" [a] -> Forall "h" a -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "h" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "h" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "h" a -> SBool) a)
-> TP (Proof (Forall "xs" [a] -> Forall "h" a -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "h" a -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "h" a -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "h" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "h" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "h" a -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "h" a -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"helper1"
                     (\(Forall @"xs" (SBV [a]
xs :: SList a)) (Forall @"h" SBV a
h) -> SBV [a] -> SBV a
forall a. SymVal a => SList a -> SBV a
head (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
destutter (SBV a
h SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)) SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
h) ((Proof (IHType (Forall "xs" [a] -> Forall "h" a -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "h" a -> SBool)
  -> IStepArgs (Forall "xs" [a] -> Forall "h" a -> SBool) a)
 -> TP (Proof (Forall "xs" [a] -> Forall "h" a -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> Forall "h" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "h" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "h" a -> SBool) a)
-> TP (Proof (Forall "xs" [a] -> Forall "h" a -> SBool))
forall a b. (a -> b) -> a -> b
$
                     \Proof (IHType (Forall "xs" [a] -> Forall "h" a -> SBool))
ih (SBV a
x, SBV [a]
xs) SBV a
h -> []
                                   [SBool] -> TPProofRaw (SBV a) -> (SBool, TPProofRaw (SBV a))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV [a] -> SBV a
forall a. SymVal a => SList a -> SBV a
head (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
destutter (SBV a
h SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs))
                                   SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBool, TPProofRaw (SBV a))] -> TPProofRaw (SBV a)
forall a. [(SBool, TPProofRaw a)] -> TPProofRaw a
cases [ SBV a
h SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
./= SBV a
x SBool -> TPProofRaw (SBV a) -> (SBool, TPProofRaw (SBV a))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> TPProofRaw (SBV a)
forall a. Trivial a => a
trivial
                                            , SBV a
h SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x SBool -> TPProofRaw (SBV a) -> (SBool, TPProofRaw (SBV a))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> SBV [a] -> SBV a
forall a. SymVal a => SList a -> SBV a
head (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
destutter (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs))
                                                       SBV a -> Proof (Forall "h" a -> SBool) -> Hinted (SBV a)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "h" a -> SBool))
Proof (Forall "h" a -> SBool)
ih
                                                       TPProofRaw (SBV a)
-> ChainsTo (TPProofRaw (SBV a)) -> ChainsTo (TPProofRaw (SBV a))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x
                                                       SBV a -> ChainsTo (SBV a) -> ChainsTo (SBV a)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV a)
TPProofRaw (SBV a)
forall a. TPProofRaw a
qed
                                            ]

   -- Helper: show that if a list has no adjacent duplicates, then destutter leaves it unchanged:
   Proof (Forall "xs" [a] -> SBool)
helper2 <- String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"helper2"
                     (\(Forall @"xs" (SBV [a]
xs :: SList a)) -> SBV [a] -> SBool
noAdd SBV [a]
xs SBool -> SBool -> SBool
.=> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
destutter SBV [a]
xs SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) [a])
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
                     \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) -> [SBV [a] -> SBool
noAdd (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)]
                                 [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
destutter (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                 SBV [a] -> Proof SBool -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                                 TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs
                                 SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed

   -- Helper: prove that noAdd is true for the result of destutter
   Proof (Forall "xs" [a] -> SBool)
helper3 <- SMTConfig
-> String
-> (Forall "xs" [a] -> SBool)
-> MeasureArgs (Forall "xs" [a] -> SBool) Integer
-> (Proof (Forall "xs" [a] -> SBool)
    -> StepArgs (Forall "xs" [a] -> SBool) Bool)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a m t.
(SInductive a, Proposition a, Zero m, SymVal t,
 EqSymbolic (SBV t)) =>
SMTConfig
-> String
-> a
-> MeasureArgs a m
-> (Proof a -> StepArgs a t)
-> TP (Proof a)
forall m t.
(Proposition (Forall "xs" [a] -> SBool), Zero m, SymVal t,
 EqSymbolic (SBV t)) =>
SMTConfig
-> String
-> (Forall "xs" [a] -> SBool)
-> MeasureArgs (Forall "xs" [a] -> SBool) m
-> (Proof (Forall "xs" [a] -> SBool)
    -> StepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
sInductWith SMTConfig
cvc5 String
"helper3"
                  (\(Forall @"xs" (SBV [a]
xs :: SList a)) -> SBV [a] -> SBool
noAdd (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
destutter SBV [a]
xs))
                  MeasureArgs (Forall "xs" [a] -> SBool) Integer
SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length ((Proof (Forall "xs" [a] -> SBool)
  -> StepArgs (Forall "xs" [a] -> SBool) Bool)
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (Forall "xs" [a] -> SBool)
    -> StepArgs (Forall "xs" [a] -> SBool) Bool)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
                  \Proof (Forall "xs" [a] -> SBool)
ih SBV [a]
xs -> []
                         [SBool] -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV [a] -> SBool
noAdd (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
destutter SBV [a]
xs)
                         SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV [a]
-> TPProofRaw SBool
-> (SBV a -> SBV [a] -> TPProofRaw SBool)
-> TPProofRaw SBool
forall a r.
SymVal a =>
SList a
-> TPProofRaw r
-> (SBV a -> SList a -> TPProofRaw r)
-> TPProofRaw r
split SBV [a]
xs
                                  TPProofRaw SBool
forall a. Trivial a => a
trivial
                                  (\SBV a
a SBV [a]
as -> SBV [a]
-> TPProofRaw SBool
-> (SBV a -> SBV [a] -> TPProofRaw SBool)
-> TPProofRaw SBool
forall a r.
SymVal a =>
SList a
-> TPProofRaw r
-> (SBV a -> SList a -> TPProofRaw r)
-> TPProofRaw r
split SBV [a]
as
                                                  TPProofRaw SBool
forall a. Trivial a => a
trivial
                                                  (\SBV a
b SBV [a]
bs -> SBV [a] -> SBool
noAdd (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
destutter (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV a
b SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
bs))
                                                         SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBool, TPProofRaw SBool)] -> TPProofRaw SBool
forall a. [(SBool, TPProofRaw a)] -> TPProofRaw a
cases [SBV a
a SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
b  SBool -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> SBV [a] -> SBool
noAdd (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
destutter (SBV a
b SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
bs))
                                                                             SBool -> Proof (Forall "xs" [a] -> SBool) -> Hinted SBool
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> SBool)
ih
                                                                             TPProofRaw SBool
-> ChainsTo (TPProofRaw SBool) -> ChainsTo (TPProofRaw SBool)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool
sTrue
                                                                             SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo SBool
TPProofRaw SBool
forall a. TPProofRaw a
qed
                                                                  , SBV a
a SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
./= SBV a
b SBool -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> SBV [a] -> SBool
noAdd (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
destutter (SBV a
b SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
bs))
                                                                             SBool -> Proof Bool -> Hinted SBool
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "h" a -> SBool)
helper1 Proof (Forall "xs" [a] -> Forall "h" a -> SBool)
-> IArgs (Forall "xs" [a] -> Forall "h" a -> SBool) -> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"xs" SBV [a]
bs, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"h" SBV a
b)
                                                                             TPProofRaw SBool
-> Proof (Forall "xs" [a] -> SBool) -> Hinted (TPProofRaw SBool)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> SBool)
ih
                                                                             Hinted (TPProofRaw SBool)
-> ChainsTo (Hinted (TPProofRaw SBool))
-> ChainsTo (Hinted (TPProofRaw SBool))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool
sTrue
                                                                             SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo SBool
TPProofRaw SBool
forall a. TPProofRaw a
qed
                                                                  ]))

   -- Now we can prove idempotency easily:
   String
-> (Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"destutterIdempotent"
          (\(Forall SBV [a]
xs) -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
destutter (SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
destutter SBV [a]
xs) SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a
destutter SBV [a]
xs)
          [Proof (Forall "xs" [a] -> SBool) -> ProofObj
forall a. Proof a -> ProofObj
proofOf Proof (Forall "xs" [a] -> SBool)
helper2, Proof (Forall "xs" [a] -> SBool) -> ProofObj
forall a. Proof a -> ProofObj
proofOf Proof (Forall "xs" [a] -> SBool)
helper3]

-- | @(as ++ bs) \\ cs == (as \\ cs) ++ (bs \\ cs)@
--
-- >>> runTP $ appendDiff @Integer
-- Inductive lemma: appendDiff
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] appendDiff :: Ɐas ∷ [Integer] → Ɐbs ∷ [Integer] → Ɐcs ∷ [Integer] → Bool
appendDiff :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
appendDiff :: forall a.
(Eq a, SymVal a) =>
TP
  (Proof
     (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
appendDiff = String
-> (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> (Proof
      (IHType
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
    -> IHArg
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
    -> IStepArgs
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
         [a])
-> TP
     (Proof
        (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
forall t.
(Proposition
   (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> (Proof
      (IHType
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
    -> IHArg
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
    -> IStepArgs
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool) t)
-> TP
     (Proof
        (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"appendDiff"
                    (\(Forall SBV [a]
as) (Forall SBV [a]
bs) (Forall SBV [a]
cs) -> (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV [a]
bs SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs)) ((Proof
    (IHType
       (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
  -> IHArg
       (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
  -> IStepArgs
       (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
       [a])
 -> TP
      (Proof
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)))
-> (Proof
      (IHType
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
    -> IHArg
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
    -> IStepArgs
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
         [a])
-> TP
     (Proof
        (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
                    \Proof
  (IHType
     (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
ih (SBV a
a, SBV [a]
as) SBV [a]
bs SBV [a]
cs -> [] [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs
                                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
bs)) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs
                                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBV [a] -> SBV [a] -> SBV [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a
a SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`elem` SBV [a]
cs) ((SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: ((SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs))
                                            SBV [a]
-> Proof (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (IHType
     (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
Proof (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
ih
                                            TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ((SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV [a]
bs SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs)
                                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed

-- | @as \\ (bs ++ cs) == (as \\ bs) \\ cs@
--
-- >>> runTP $ diffAppend @Integer
-- Inductive lemma: diffAppend
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] diffAppend :: Ɐas ∷ [Integer] → Ɐbs ∷ [Integer] → Ɐcs ∷ [Integer] → Bool
diffAppend :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
diffAppend :: forall a.
(Eq a, SymVal a) =>
TP
  (Proof
     (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
diffAppend = String
-> (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> (Proof
      (IHType
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
    -> IHArg
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
    -> IStepArgs
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
         [a])
-> TP
     (Proof
        (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
forall t.
(Proposition
   (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> (Proof
      (IHType
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
    -> IHArg
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
    -> IStepArgs
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool) t)
-> TP
     (Proof
        (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"diffAppend"
                    (\(Forall SBV [a]
as) (Forall SBV [a]
bs) (Forall SBV [a]
cs) -> SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ (SBV [a]
bs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
cs) SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) ((Proof
    (IHType
       (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
  -> IHArg
       (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
  -> IStepArgs
       (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
       [a])
 -> TP
      (Proof
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)))
-> (Proof
      (IHType
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
    -> IHArg
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
    -> IStepArgs
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
         [a])
-> TP
     (Proof
        (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
                    \Proof
  (IHType
     (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
ih (SBV a
a, SBV [a]
as) SBV [a]
bs SBV [a]
cs -> [] [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ (SBV [a]
bs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
cs)
                                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBV [a] -> SBV [a] -> SBV [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a
a SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`elem` (SBV [a]
bs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
cs)) (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ (SBV [a]
bs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
cs)) (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ (SBV [a]
bs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
cs)))
                                            SBV [a] -> Proof Bool -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (IHType
     (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
Proof (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
ih Proof (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> IArgs (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"bs" SBV [a]
bs, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"cs" SBV [a]
cs)
                                            TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBV [a] -> SBV [a] -> SBV [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a
a SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`elem` (SBV [a]
bs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
cs)) ((SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ (SBV [a]
bs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
cs)))
                                            SBV [a] -> Proof Bool -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (IHType
     (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
Proof (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
ih Proof (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> IArgs (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"bs" SBV [a]
bs, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"cs" SBV [a]
cs)
                                            TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBV [a] -> SBV [a] -> SBV [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a
a SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`elem` (SBV [a]
bs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
cs)) ((SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: ((SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs))
                                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ((SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs
                                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed

-- | @(as \\ bs) \\ cs == (as \\ cs) \\ bs@
--
-- >>> runTP $ diffDiff @Integer
-- Inductive lemma: diffDiff
--   Step: Base                            Q.E.D.
--   Step: 1 (2 way case split)
--     Step: 1.1.1                         Q.E.D.
--     Step: 1.1.2                         Q.E.D.
--     Step: 1.1.3 (2 way case split)
--       Step: 1.1.3.1                     Q.E.D.
--       Step: 1.1.3.2.1                   Q.E.D.
--       Step: 1.1.3.2.2 (a ∉ cs)          Q.E.D.
--       Step: 1.1.3.Completeness          Q.E.D.
--     Step: 1.2.1                         Q.E.D.
--     Step: 1.2.2 (2 way case split)
--       Step: 1.2.2.1.1                   Q.E.D.
--       Step: 1.2.2.1.2                   Q.E.D.
--       Step: 1.2.2.1.3 (a ∈ cs)          Q.E.D.
--       Step: 1.2.2.2.1                   Q.E.D.
--       Step: 1.2.2.2.2                   Q.E.D.
--       Step: 1.2.2.2.3 (a ∉ bs)          Q.E.D.
--       Step: 1.2.2.2.4 (a ∉ cs)          Q.E.D.
--       Step: 1.2.2.Completeness          Q.E.D.
--     Step: 1.Completeness                Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] diffDiff :: Ɐas ∷ [Integer] → Ɐbs ∷ [Integer] → Ɐcs ∷ [Integer] → Bool
diffDiff :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
diffDiff :: forall a.
(Eq a, SymVal a) =>
TP
  (Proof
     (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
diffDiff = String
-> (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> (Proof
      (IHType
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
    -> IHArg
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
    -> IStepArgs
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
         [a])
-> TP
     (Proof
        (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
forall t.
(Proposition
   (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> (Proof
      (IHType
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
    -> IHArg
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
    -> IStepArgs
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool) t)
-> TP
     (Proof
        (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"diffDiff"
                  (\(Forall SBV [a]
as) (Forall SBV [a]
bs) (Forall SBV [a]
cs) -> (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs) ((Proof
    (IHType
       (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
  -> IHArg
       (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
  -> IStepArgs
       (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
       [a])
 -> TP
      (Proof
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)))
-> (Proof
      (IHType
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
    -> IHArg
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
    -> IStepArgs
         (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool)
         [a])
-> TP
     (Proof
        (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
                  \Proof
  (IHType
     (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
ih (SBV a
a, SBV [a]
as) SBV [a]
bs SBV [a]
cs ->
                      [] [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- ((SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs
                         SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBool, TPProofRaw (SBV [a]))] -> TPProofRaw (SBV [a])
forall a. [(SBool, TPProofRaw a)] -> TPProofRaw a
cases [ SBV a
a SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`elem`    SBV [a]
bs SBool -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs
                                                    SBV [a]
-> Proof (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (IHType
     (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
Proof (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
ih
                                                    TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs
                                                    SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBool, TPProofRaw (SBV [a]))] -> TPProofRaw (SBV [a])
forall a. [(SBool, TPProofRaw a)] -> TPProofRaw a
cases [ SBV a
a SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`elem`    SBV [a]
cs SBool -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> ((SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs
                                                                               SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed
                                                             , SBV a
a SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`notElem` SBV [a]
cs SBool -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs)) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs
                                                                               SBV [a] -> String -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? String
"a ∉ cs"
                                                                               TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ((SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs
                                                                               SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed
                                                             ]
                                  , SBV a
a SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`notElem` SBV [a]
bs SBool -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs)) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs
                                                    SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBool, TPProofRaw (SBV [a]))] -> TPProofRaw (SBV [a])
forall a. [(SBool, TPProofRaw a)] -> TPProofRaw a
cases [ SBV a
a SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`elem`    SBV [a]
cs SBool -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs
                                                                               SBV [a]
-> Proof (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (IHType
     (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
Proof (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
ih
                                                                               TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs
                                                                               SBV [a] -> String -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? String
"a ∈ cs"
                                                                               TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ((SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs
                                                                               SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed
                                                             , SBV a
a SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`notElem` SBV [a]
cs SBool -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: ((SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs)
                                                                               SBV [a]
-> Proof (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
-> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (IHType
     (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
Proof (Forall "bs" [a] -> Forall "cs" [a] -> SBool)
ih
                                                                               TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: ((SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs)
                                                                               SBV [a] -> String -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? String
"a ∉ bs"
                                                                               TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs)) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs
                                                                               SBV [a] -> String -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? String
"a ∉ cs"
                                                                               TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ((SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
cs) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs
                                                                               SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed
                                                             ]
                                  ]

-- | Are the two lists disjoint?
disjoint :: (Eq a, SymVal a) => SList a -> SList a -> SBool
disjoint :: forall a. (Eq a, SymVal a) => SList a -> SList a -> SBool
disjoint = String
-> (SList a -> SList a -> SBool) -> SList a -> SList a -> SBool
forall a.
(SMTDefinable a, Typeable a, Lambda Symbolic a) =>
String -> a -> a
smtFunction String
"disjoint" ((SList a -> SList a -> SBool) -> SList a -> SList a -> SBool)
-> (SList a -> SList a -> SBool) -> SList a -> SList a -> SBool
forall a b. (a -> b) -> a -> b
$ \SList a
xs SList a
ys -> SList a -> SBool
forall a. SymVal a => SList a -> SBool
null SList a
xs SBool -> SBool -> SBool
.|| SList a -> SBV a
forall a. SymVal a => SList a -> SBV a
head SList a
xs SBV a -> SList a -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`notElem` SList a
ys SBool -> SBool -> SBool
.&& SList a -> SList a -> SBool
forall a. (Eq a, SymVal a) => SList a -> SList a -> SBool
disjoint (SList a -> SList a
forall a. SymVal a => SList a -> SList a
tail SList a
xs) SList a
ys

-- | @disjoint as bs .=> as \\ bs == as@
--
-- >>> runTP $ disjointDiff @Integer
-- Inductive lemma: disjointDiff
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] disjointDiff :: Ɐas ∷ [Integer] → Ɐbs ∷ [Integer] → Bool
disjointDiff :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "as" [a] -> Forall "bs" [a] -> SBool))
disjointDiff :: forall a.
(Eq a, SymVal a) =>
TP (Proof (Forall "as" [a] -> Forall "bs" [a] -> SBool))
disjointDiff = String
-> (Forall "as" [a] -> Forall "bs" [a] -> SBool)
-> (Proof (IHType (Forall "as" [a] -> Forall "bs" [a] -> SBool))
    -> IHArg (Forall "as" [a] -> Forall "bs" [a] -> SBool)
    -> IStepArgs (Forall "as" [a] -> Forall "bs" [a] -> SBool) [a])
-> TP (Proof (Forall "as" [a] -> Forall "bs" [a] -> SBool))
forall t.
(Proposition (Forall "as" [a] -> Forall "bs" [a] -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "as" [a] -> Forall "bs" [a] -> SBool)
-> (Proof (IHType (Forall "as" [a] -> Forall "bs" [a] -> SBool))
    -> IHArg (Forall "as" [a] -> Forall "bs" [a] -> SBool)
    -> IStepArgs (Forall "as" [a] -> Forall "bs" [a] -> SBool) t)
-> TP (Proof (Forall "as" [a] -> Forall "bs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"disjointDiff"
                      (\(Forall SBV [a]
as) (Forall SBV [a]
bs) -> SBV [a] -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SList a -> SList a -> SBool
disjoint SBV [a]
as SBV [a]
bs SBool -> SBool -> SBool
.=> SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [a]
as) ((Proof (IHType (Forall "as" [a] -> Forall "bs" [a] -> SBool))
  -> IHArg (Forall "as" [a] -> Forall "bs" [a] -> SBool)
  -> IStepArgs (Forall "as" [a] -> Forall "bs" [a] -> SBool) [a])
 -> TP (Proof (Forall "as" [a] -> Forall "bs" [a] -> SBool)))
-> (Proof (IHType (Forall "as" [a] -> Forall "bs" [a] -> SBool))
    -> IHArg (Forall "as" [a] -> Forall "bs" [a] -> SBool)
    -> IStepArgs (Forall "as" [a] -> Forall "bs" [a] -> SBool) [a])
-> TP (Proof (Forall "as" [a] -> Forall "bs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
                      \Proof (IHType (Forall "as" [a] -> Forall "bs" [a] -> SBool))
ih (SBV a
a, SBV [a]
as) SBV [a]
bs -> [SBV [a] -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SList a -> SList a -> SBool
disjoint (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as) SBV [a]
bs]
                                     [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as) SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs
                                     SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV [a]
as SBV [a] -> SBV [a] -> SBV [a]
forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
\\ SBV [a]
bs)
                                     SBV [a] -> Proof (Forall "bs" [a] -> SBool) -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "as" [a] -> Forall "bs" [a] -> SBool))
Proof (Forall "bs" [a] -> SBool)
ih
                                     TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as
                                     SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed

-- | @fst (partition f xs) == filter f xs@
--
-- >>> runTP $ partition1 @Integer (uninterpret "f")
-- Inductive lemma: partition1
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] partition1 :: Ɐxs ∷ [Integer] → Bool
partition1 :: forall a. SymVal a => (SBV a -> SBool) -> TP (Proof (Forall "xs" [a] -> SBool))
partition1 :: forall a.
SymVal a =>
(SBV a -> SBool) -> TP (Proof (Forall "xs" [a] -> SBool))
partition1 SBV a -> SBool
f =
   String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"partition1"
          (\(Forall SBV [a]
xs) -> STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst ((SBV a -> SBool) -> SBV [a] -> STuple [a] [a]
forall func a. SFilter func a => func -> SList a -> STuple [a] [a]
partition SBV a -> SBool
f SBV [a]
xs) SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
f SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) [a])
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) -> [] [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst ((SBV a -> SBool) -> SBV [a] -> STuple [a] [a]
forall func a. SFilter func a => func -> SList a -> STuple [a] [a]
partition SBV a -> SBool
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs))
                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst (let res :: STuple [a] [a]
res = (SBV a -> SBool) -> SBV [a] -> STuple [a] [a]
forall func a. SFilter func a => func -> SList a -> STuple [a] [a]
partition SBV a -> SBool
f SBV [a]
xs
                                    in SBool -> STuple [a] [a] -> STuple [a] [a] -> STuple [a] [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a -> SBool
f SBV a
x)
                                           ((SBV [a], SBV [a]) -> STuple [a] [a]
forall tup a. Tuple tup a => a -> SBV tup
tuple (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst STuple [a] [a]
res, STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd STuple [a] [a]
res))
                                           ((SBV [a], SBV [a]) -> STuple [a] [a]
forall tup a. Tuple tup a => a -> SBV tup
tuple (STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst STuple [a] [a]
res, SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd STuple [a] [a]
res)))
                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBV [a] -> SBV [a] -> SBV [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a -> SBool
f SBV a
x) (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst ((SBV a -> SBool) -> SBV [a] -> STuple [a] [a]
forall func a. SFilter func a => func -> SList a -> STuple [a] [a]
partition SBV a -> SBool
f SBV [a]
xs)) (STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst ((SBV a -> SBool) -> SBV [a] -> STuple [a] [a]
forall func a. SFilter func a => func -> SList a -> STuple [a] [a]
partition SBV a -> SBool
f SBV [a]
xs))
                            SBV [a] -> Proof SBool -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                            TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBV [a] -> SBV [a] -> SBV [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a -> SBool
f SBV a
x) (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
f SBV [a]
xs) ((SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
f SBV [a]
xs)
                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter SBV a -> SBool
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed

-- | @snd (partition f xs) == filter (not . f) xs@
--
-- >>> runTP $ partition2 @Integer (uninterpret "f")
-- Inductive lemma: partition2
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] partition2 :: Ɐxs ∷ [Integer] → Bool
partition2 :: forall a. SymVal a => (SBV a -> SBool) -> TP (Proof (Forall "xs" [a] -> SBool))
partition2 :: forall a.
SymVal a =>
(SBV a -> SBool) -> TP (Proof (Forall "xs" [a] -> SBool))
partition2 SBV a -> SBool
f =
   String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"partition2"
          (\(Forall SBV [a]
xs) -> STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd ((SBV a -> SBool) -> SBV [a] -> STuple [a] [a]
forall func a. SFilter func a => func -> SList a -> STuple [a] [a]
partition SBV a -> SBool
f SBV [a]
xs) SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter (SBool -> SBool
sNot (SBool -> SBool) -> (SBV a -> SBool) -> SBV a -> SBool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBV a -> SBool
f) SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> SBool))
  -> IHArg (Forall "xs" [a] -> SBool)
  -> IStepArgs (Forall "xs" [a] -> SBool) [a])
 -> TP (Proof (Forall "xs" [a] -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> SBool))
    -> IHArg (Forall "xs" [a] -> SBool)
    -> IStepArgs (Forall "xs" [a] -> SBool) [a])
-> TP (Proof (Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> SBool))
ih (SBV a
x, SBV [a]
xs) -> [] [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd ((SBV a -> SBool) -> SBV [a] -> STuple [a] [a]
forall func a. SFilter func a => func -> SList a -> STuple [a] [a]
partition SBV a -> SBool
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs))
                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd (let res :: STuple [a] [a]
res = (SBV a -> SBool) -> SBV [a] -> STuple [a] [a]
forall func a. SFilter func a => func -> SList a -> STuple [a] [a]
partition SBV a -> SBool
f SBV [a]
xs
                                    in SBool -> STuple [a] [a] -> STuple [a] [a] -> STuple [a] [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a -> SBool
f SBV a
x)
                                           ((SBV [a], SBV [a]) -> STuple [a] [a]
forall tup a. Tuple tup a => a -> SBV tup
tuple (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst STuple [a] [a]
res, STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd STuple [a] [a]
res))
                                           ((SBV [a], SBV [a]) -> STuple [a] [a]
forall tup a. Tuple tup a => a -> SBV tup
tuple (STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst STuple [a] [a]
res, SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd STuple [a] [a]
res)))
                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBV [a] -> SBV [a] -> SBV [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a -> SBool
f SBV a
x) (STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd ((SBV a -> SBool) -> SBV [a] -> STuple [a] [a]
forall func a. SFilter func a => func -> SList a -> STuple [a] [a]
partition SBV a -> SBool
f SBV [a]
xs)) (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: STuple [a] [a] -> SBV [a]
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd ((SBV a -> SBool) -> SBV [a] -> STuple [a] [a]
forall func a. SFilter func a => func -> SList a -> STuple [a] [a]
partition SBV a -> SBool
f SBV [a]
xs))
                            SBV [a] -> Proof SBool -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType (Forall "xs" [a] -> SBool))
ih
                            TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBV [a] -> SBV [a] -> SBV [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a -> SBool
f SBV a
x) ((SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter (SBool -> SBool
sNot (SBool -> SBool) -> (SBV a -> SBool) -> SBV a -> SBool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBV a -> SBool
f) SBV [a]
xs) (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter (SBool -> SBool
sNot (SBool -> SBool) -> (SBV a -> SBool) -> SBV a -> SBool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBV a -> SBool
f) SBV [a]
xs)
                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBool) -> SBV [a] -> SBV [a]
forall func a. SFilter func a => func -> SList a -> SList a
filter (SBool -> SBool
sNot (SBool -> SBool) -> (SBV a -> SBool) -> SBV a -> SBool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBV a -> SBool
f) (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                            SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed

-- | @take n (take m xs) == take (n `smin` m) xs@
--
-- >>> runTP $ take_take @Integer
-- Lemma: take_take                        Q.E.D.
-- [Proven] take_take :: Ɐm ∷ Integer → Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
take_take :: forall a. SymVal a => TP (Proof (Forall "m" Integer -> Forall "n" Integer -> Forall "xs" [a] -> SBool))
take_take :: forall a.
SymVal a =>
TP
  (Proof
     (Forall "m" Integer
      -> Forall "n" Integer -> Forall "xs" [a] -> SBool))
take_take = String
-> (Forall "m" Integer
    -> Forall "n" Integer -> Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP
     (Proof
        (Forall "m" Integer
         -> Forall "n" Integer -> Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"take_take"
                  (\(Forall SBV Integer
m) (Forall SBV Integer
n) (Forall SList a
xs) -> SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n (SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
m SList a
xs) SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV Integer
n SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smin` SBV Integer
m) SList a
xs)
                  []

-- | @n >= 0 && m >= 0 ==> drop n (drop m xs) == drop (n + m) xs@
--
-- >>> runTP $ drop_drop @Integer
-- Lemma: drop_drop                        Q.E.D.
-- [Proven] drop_drop :: Ɐm ∷ Integer → Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
drop_drop :: forall a. SymVal a => TP (Proof (Forall "m" Integer -> Forall "n" Integer -> Forall "xs" [a] -> SBool))
drop_drop :: forall a.
SymVal a =>
TP
  (Proof
     (Forall "m" Integer
      -> Forall "n" Integer -> Forall "xs" [a] -> SBool))
drop_drop = String
-> (Forall "m" Integer
    -> Forall "n" Integer -> Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP
     (Proof
        (Forall "m" Integer
         -> Forall "n" Integer -> Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"drop_drop"
                  (\(Forall SBV Integer
m) (Forall SBV Integer
n) (Forall SList a
xs) -> SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= SBV Integer
0 SBool -> SBool -> SBool
.&& SBV Integer
m SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= SBV Integer
0 SBool -> SBool -> SBool
.=> SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n (SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
m SList a
xs) SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop (SBV Integer
n SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV Integer
m) SList a
xs)
                  []

-- | @take n xs ++ drop n xs == xs@
--
-- >>> runTP $ take_drop @Integer
-- Lemma: take_drop                        Q.E.D.
-- [Proven] take_drop :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
take_drop :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
take_drop :: forall a.
SymVal a =>
TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
take_drop = String
-> (Forall "n" Integer -> Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"take_drop"
                  (\(Forall SBV Integer
n) (Forall SList a
xs) -> SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n SList a
xs SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SList a
xs)
                  []

-- | @n .> 0 ==> take n (x .: xs) == x .: take (n - 1) xs@
--
-- >>> runTP $ take_cons @Integer
-- Lemma: take_cons                        Q.E.D.
-- [Proven] take_cons :: Ɐn ∷ Integer → Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Bool
take_cons :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool))
take_cons :: forall a.
SymVal a =>
TP
  (Proof
     (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool))
take_cons = String
-> (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP
     (Proof
        (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"take_cons"
                  (\(Forall SBV Integer
n) (Forall SBV a
x) (Forall SList a
xs) -> SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0 SBool -> SBool -> SBool
.=> SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs) SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV Integer
n SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SBV Integer
1) SList a
xs)
                  []

-- | @take n (map f xs) == map f (take n xs)@
--
-- >>> runTP $ take_map @Integer @Integer (uninterpret "f")
-- Lemma: take_cons                        Q.E.D.
-- Lemma: map1                             Q.E.D.
-- Lemma: take_map.n <= 0                  Q.E.D.
-- Inductive lemma: take_map.n > 0
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Result:                               Q.E.D.
-- Lemma: take_map
--   Step: 1                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] take_map :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
take_map :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b) -> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
take_map :: forall a b.
(SymVal a, SymVal b) =>
(SBV a -> SBV b)
-> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
take_map SBV a -> SBV b
f = do
    Proof
  (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
tc   <- forall a.
SymVal a =>
TP
  (Proof
     (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool))
take_cons @a

    Proof (Forall "x" a -> Forall "xs" [a] -> SBool)
map1 <- String
-> (Forall "x" a -> Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"map1"
                  (\(Forall SBV a
x) (Forall SBV [a]
xs) -> (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a -> SBV b
f SBV a
x SBV b -> SList b -> SList b
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs)
                  []

    Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)
h1 <- String
-> (Forall "xs" [a] -> Forall "n" Integer -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"take_map.n <= 0"
                 (\(Forall @"xs" SBV [a]
xs) (Forall @"n" SBV Integer
n) -> SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.<= SBV Integer
0 SBool -> SBool -> SBool
.=> SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs) SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n SBV [a]
xs))
                 []

    Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)
h2 <- String
-> (Forall "xs" [a] -> Forall "n" Integer -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "n" Integer -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "n" Integer -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "n" Integer -> SBool) [b])
-> TP (Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "n" Integer -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "n" Integer -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "n" Integer -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "n" Integer -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "n" Integer -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"take_map.n > 0"
                 (\(Forall @"xs" SBV [a]
xs) (Forall @"n" SBV Integer
n) -> SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0 SBool -> SBool -> SBool
.=> SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs) SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n SBV [a]
xs)) ((Proof (IHType (Forall "xs" [a] -> Forall "n" Integer -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "n" Integer -> SBool)
  -> IStepArgs (Forall "xs" [a] -> Forall "n" Integer -> SBool) [b])
 -> TP (Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> Forall "n" Integer -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "n" Integer -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "n" Integer -> SBool) [b])
-> TP (Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool))
forall a b. (a -> b) -> a -> b
$
                 \Proof (IHType (Forall "xs" [a] -> Forall "n" Integer -> SBool))
ih (SBV a
x, SBV [a]
xs) SBV Integer
n -> [SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0] [SBool] -> TPProofRaw (SList b) -> (SBool, TPProofRaw (SList b))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs))
                                           SList b -> ChainsTo (SList b) -> ChainsTo (SList b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n (SBV a -> SBV b
f SBV a
x SBV b -> SList b -> SList b
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs)
                                           SList b -> ChainsTo (SList b) -> ChainsTo (SList b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV b
f SBV a
x SBV b -> SList b -> SList b
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV Integer
n SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SBV Integer
1) ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs)
                                           SList b -> Proof Bool -> Hinted (SList b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "n" Integer -> SBool))
Proof (Forall "n" Integer -> SBool)
ih Proof (Forall "n" Integer -> SBool)
-> IArgs (Forall "n" Integer -> SBool) -> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"n" (SBV Integer
nSBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
-SBV Integer
1)
                                           TPProofRaw (SList b)
-> ChainsTo (TPProofRaw (SList b))
-> ChainsTo (TPProofRaw (SList b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV b
f SBV a
x SBV b -> SList b -> SList b
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV Integer
n SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SBV Integer
1) SBV [a]
xs)
                                           SList b -> Proof Bool -> Hinted (SList b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "x" a -> Forall "xs" [a] -> SBool)
map1 Proof (Forall "x" a -> Forall "xs" [a] -> SBool)
-> IArgs (Forall "x" a -> Forall "xs" [a] -> SBool) -> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"x" SBV a
x, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"xs" (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV Integer
n SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SBV Integer
1) SBV [a]
xs))
                                           TPProofRaw (SList b)
-> ChainsTo (TPProofRaw (SList b))
-> ChainsTo (TPProofRaw (SList b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV Integer
n SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SBV Integer
1) SBV [a]
xs)
                                           SList b
-> Proof
     (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
-> Hinted (SList b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
tc
                                           TPProofRaw (SList b)
-> ChainsTo (TPProofRaw (SList b))
-> ChainsTo (TPProofRaw (SList b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs))
                                           SList b -> ChainsTo (SList b) -> ChainsTo (SList b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SList b)
TPProofRaw (SList b)
forall a. TPProofRaw a
qed

    String
-> (Forall "n" Integer -> Forall "xs" [a] -> SBool)
-> StepArgs (Forall "n" Integer -> Forall "xs" [a] -> SBool) [b]
-> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "n" Integer -> Forall "xs" [a] -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "n" Integer -> Forall "xs" [a] -> SBool)
-> StepArgs (Forall "n" Integer -> Forall "xs" [a] -> SBool) t
-> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
forall a t.
(Calc a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String -> a -> StepArgs a t -> TP (Proof a)
calc String
"take_map"
         (\(Forall SBV Integer
n) (Forall SBV [a]
xs) -> SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs) SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n SBV [a]
xs)) (StepArgs (Forall "n" Integer -> Forall "xs" [a] -> SBool) [b]
 -> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool)))
-> StepArgs (Forall "n" Integer -> Forall "xs" [a] -> SBool) [b]
-> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
         \SBV Integer
n SBV [a]
xs -> [] [SBool] -> TPProofRaw (SList b) -> (SBool, TPProofRaw (SList b))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs)
                     SList b
-> Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)
-> Hinted (SList b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)
h1
                     TPProofRaw (SList b)
-> Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)
-> Hinted (TPProofRaw (SList b))
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)
h2
                     Hinted (TPProofRaw (SList b))
-> ChainsTo (Hinted (TPProofRaw (SList b)))
-> ChainsTo (Hinted (TPProofRaw (SList b)))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n SBV [a]
xs)
                     SList b -> ChainsTo (SList b) -> ChainsTo (SList b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SList b)
TPProofRaw (SList b)
forall a. TPProofRaw a
qed

-- | @n .> 0 ==> drop n (x .: xs) == drop (n - 1) xs@
--
-- >>> runTP $ drop_cons @Integer
-- Lemma: drop_cons                        Q.E.D.
-- [Proven] drop_cons :: Ɐn ∷ Integer → Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Bool
drop_cons :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool))
drop_cons :: forall a.
SymVal a =>
TP
  (Proof
     (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool))
drop_cons = String
-> (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP
     (Proof
        (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"drop_cons"
                  (\(Forall SBV Integer
n) (Forall SBV a
x) (Forall SList a
xs) -> SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0 SBool -> SBool -> SBool
.=> SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n (SBV a
x SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
xs) SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop (SBV Integer
n SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SBV Integer
1) SList a
xs)
                  []

-- | @drop n (map f xs) == map f (drop n xs)@
--
-- >>> runTP $ drop_map @Integer @String (uninterpret "f")
-- Lemma: drop_cons                        Q.E.D.
-- Lemma: drop_cons                        Q.E.D.
-- Lemma: drop_map.n <= 0                  Q.E.D.
-- Inductive lemma: drop_map.n > 0
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- Lemma: drop_map
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] drop_map :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
drop_map :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b) -> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
drop_map :: forall a b.
(SymVal a, SymVal b) =>
(SBV a -> SBV b)
-> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
drop_map SBV a -> SBV b
f = do
   Proof
  (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
dcA <- forall a.
SymVal a =>
TP
  (Proof
     (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool))
drop_cons @a
   Proof
  (Forall "n" Integer -> Forall "x" b -> Forall "xs" [b] -> SBool)
dcB <- forall a.
SymVal a =>
TP
  (Proof
     (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool))
drop_cons @b

   Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)
h1 <- String
-> (Forall "xs" [a] -> Forall "n" Integer -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"drop_map.n <= 0"
               (\(Forall @"xs" SBV [a]
xs) (Forall @"n" SBV Integer
n) -> SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.<= SBV Integer
0 SBool -> SBool -> SBool
.=> SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs) SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n SBV [a]
xs))
               []

   Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)
h2 <- String
-> (Forall "xs" [a] -> Forall "n" Integer -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "n" Integer -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "n" Integer -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "n" Integer -> SBool) [b])
-> TP (Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "n" Integer -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "n" Integer -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "n" Integer -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "n" Integer -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "n" Integer -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"drop_map.n > 0"
                (\(Forall @"xs" SBV [a]
xs) (Forall @"n" SBV Integer
n) -> SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0 SBool -> SBool -> SBool
.=> SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs) SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n SBV [a]
xs)) ((Proof (IHType (Forall "xs" [a] -> Forall "n" Integer -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "n" Integer -> SBool)
  -> IStepArgs (Forall "xs" [a] -> Forall "n" Integer -> SBool) [b])
 -> TP (Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> Forall "n" Integer -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "n" Integer -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "n" Integer -> SBool) [b])
-> TP (Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool))
forall a b. (a -> b) -> a -> b
$
                \Proof (IHType (Forall "xs" [a] -> Forall "n" Integer -> SBool))
ih (SBV a
x, SBV [a]
xs) SBV Integer
n -> [SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0] [SBool] -> TPProofRaw (SList b) -> (SBool, TPProofRaw (SList b))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs))
                                          SList b -> ChainsTo (SList b) -> ChainsTo (SList b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n (SBV a -> SBV b
f SBV a
x SBV b -> SList b -> SList b
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs)
                                          SList b -> Proof Bool -> Hinted (SList b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (Forall "n" Integer -> Forall "x" b -> Forall "xs" [b] -> SBool)
dcB Proof
  (Forall "n" Integer -> Forall "x" b -> Forall "xs" [b] -> SBool)
-> IArgs
     (Forall "n" Integer -> Forall "x" b -> Forall "xs" [b] -> SBool)
-> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"n" SBV Integer
n, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"x" (SBV a -> SBV b
f SBV a
x), forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"xs" ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs))
                                          TPProofRaw (SList b)
-> ChainsTo (TPProofRaw (SList b))
-> ChainsTo (TPProofRaw (SList b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop (SBV Integer
n SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SBV Integer
1) ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs)
                                          SList b -> Proof Bool -> Hinted (SList b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "n" Integer -> SBool))
Proof (Forall "n" Integer -> SBool)
ih Proof (Forall "n" Integer -> SBool)
-> IArgs (Forall "n" Integer -> SBool) -> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"n" (SBV Integer
nSBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
-SBV Integer
1)
                                          TPProofRaw (SList b)
-> ChainsTo (TPProofRaw (SList b))
-> ChainsTo (TPProofRaw (SList b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop (SBV Integer
n SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SBV Integer
1) SBV [a]
xs)
                                          SList b -> Proof Bool -> Hinted (SList b)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
dcA Proof
  (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
-> IArgs
     (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
-> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"n" SBV Integer
n, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"x" SBV a
x, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"xs" SBV [a]
xs)
                                          TPProofRaw (SList b)
-> ChainsTo (TPProofRaw (SList b))
-> ChainsTo (TPProofRaw (SList b))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs))
                                          SList b -> ChainsTo (SList b) -> ChainsTo (SList b)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SList b)
TPProofRaw (SList b)
forall a. TPProofRaw a
qed

   -- I'm a bit surprised that z3 can't deduce the following with a simple-lemma, which is essentially a simple case-split.
   -- But the good thing about calc is that it lets us direct the tool in precise ways that we'd like.
   String
-> (Forall "n" Integer -> Forall "xs" [a] -> SBool)
-> StepArgs (Forall "n" Integer -> Forall "xs" [a] -> SBool) Bool
-> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
forall t.
(Proposition (Forall "n" Integer -> Forall "xs" [a] -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "n" Integer -> Forall "xs" [a] -> SBool)
-> StepArgs (Forall "n" Integer -> Forall "xs" [a] -> SBool) t
-> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
forall a t.
(Calc a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String -> a -> StepArgs a t -> TP (Proof a)
calc String
"drop_map"
        (\(Forall SBV Integer
n) (Forall SBV [a]
xs) -> SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs) SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n SBV [a]
xs)) (StepArgs (Forall "n" Integer -> Forall "xs" [a] -> SBool) Bool
 -> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool)))
-> StepArgs (Forall "n" Integer -> Forall "xs" [a] -> SBool) Bool
-> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
        \SBV Integer
n SBV [a]
xs -> [] [SBool] -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- let result :: SBool
result = SBV Integer -> SList b -> SList b
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n ((SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f SBV [a]
xs) SList b -> SList b -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV a -> SBV b) -> SBV [a] -> SList b
forall func a b. SMap func a b => func -> SList a -> SList b
map SBV a -> SBV b
f (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n SBV [a]
xs)
                       in SBool
result
                       SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBool -> SBool -> SBool
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.<= SBV Integer
0) (SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.<= SBV Integer
0 SBool -> SBool -> SBool
.=> SBool
result) (SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0 SBool -> SBool -> SBool
.=> SBool
result)
                       SBool
-> Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)
-> Hinted SBool
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)
h1
                       TPProofRaw SBool
-> ChainsTo (TPProofRaw SBool) -> ChainsTo (TPProofRaw SBool)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBool -> SBool -> SBool
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.<= SBV Integer
0) SBool
sTrue (SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0 SBool -> SBool -> SBool
.=> SBool
result)
                       SBool
-> Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)
-> Hinted SBool
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "n" Integer -> SBool)
h2
                       TPProofRaw SBool
-> ChainsTo (TPProofRaw SBool) -> ChainsTo (TPProofRaw SBool)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool -> SBool -> SBool -> SBool
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.<= SBV Integer
0) SBool
sTrue SBool
sTrue
                       SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool
sTrue
                       SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo SBool
TPProofRaw SBool
forall a. TPProofRaw a
qed

-- | @n >= 0 ==> length (take n xs) == length xs \`min\` n@
--
-- >>> runTP $ length_take @Integer
-- Lemma: length_take                      Q.E.D.
-- [Proven] length_take :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
length_take :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
length_take :: forall a.
SymVal a =>
TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
length_take = String
-> (Forall "n" Integer -> Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"length_take"
                    (\(Forall SBV Integer
n) (Forall SBV [a]
xs) -> SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= SBV Integer
0 SBool -> SBool -> SBool
.=> SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n SBV [a]
xs) SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smin` SBV Integer
n)
                    []

-- | @n >= 0 ==> length (drop n xs) == (length xs - n) \`max\` 0@
--
-- >>> runTP $ length_drop @Integer
-- Lemma: length_drop                      Q.E.D.
-- [Proven] length_drop :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
length_drop :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
length_drop :: forall a.
SymVal a =>
TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
length_drop = String
-> (Forall "n" Integer -> Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"length_drop"
                    (\(Forall SBV Integer
n) (Forall SBV [a]
xs) -> SBV Integer
n SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= SBV Integer
0 SBool -> SBool -> SBool
.=> SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n SBV [a]
xs) SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SBV Integer
n) SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smax` SBV Integer
0)
                    []

-- | @length xs \<= n ==\> take n xs == xs@
--
-- >>> runTP $ take_all @Integer
-- Lemma: take_all                         Q.E.D.
-- [Proven] take_all :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
take_all :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
take_all :: forall a.
SymVal a =>
TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
take_all = String
-> (Forall "n" Integer -> Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"take_all"
                 (\(Forall SBV Integer
n) (Forall SList a
xs) -> SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
xs SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.<= SBV Integer
n SBool -> SBool -> SBool
.=> SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n SList a
xs SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SList a
xs)
                 []

-- | @length xs \<= n ==\> drop n xs == nil@
--
-- >>> runTP $ drop_all @Integer
-- Lemma: drop_all                         Q.E.D.
-- [Proven] drop_all :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
drop_all :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
drop_all :: forall a.
SymVal a =>
TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
drop_all = String
-> (Forall "n" Integer -> Forall "xs" [a] -> SBool)
-> [ProofObj]
-> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"drop_all"
                 (\(Forall SBV Integer
n) (Forall SList a
xs) -> SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
xs SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.<= SBV Integer
n SBool -> SBool -> SBool
.=> SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n SList a
xs SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SList a
forall a. SymVal a => SList a
nil)
                 []

-- | @take n (xs ++ ys) == (take n xs ++ take (n - length xs) ys)@
--
-- >>> runTP $ take_append @Integer
-- Lemma: take_append                      Q.E.D.
-- [Proven] take_append :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
take_append :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
take_append :: forall a.
SymVal a =>
TP
  (Proof
     (Forall "n" Integer
      -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
take_append = SMTConfig
-> String
-> (Forall "n" Integer
    -> Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> [ProofObj]
-> TP
     (Proof
        (Forall "n" Integer
         -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a.
Proposition a =>
SMTConfig -> String -> a -> [ProofObj] -> TP (Proof a)
lemmaWith SMTConfig
cvc5 String
"take_append"
                        (\(Forall SBV Integer
n) (Forall SList a
xs) (Forall SList a
ys) -> SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n (SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys) SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV Integer
n SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
xs) SList a
ys)
                        []

-- | @drop n (xs ++ ys) == drop n xs ++ drop (n - length xs) ys@
--
-- NB. As of Feb 2025, z3 struggles to prove this, but cvc5 gets it out-of-the-box.
--
-- >>> runTP $ drop_append @Integer
-- Lemma: drop_append                      Q.E.D.
-- [Proven] drop_append :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
drop_append :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
drop_append :: forall a.
SymVal a =>
TP
  (Proof
     (Forall "n" Integer
      -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
drop_append = SMTConfig
-> String
-> (Forall "n" Integer
    -> Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> [ProofObj]
-> TP
     (Proof
        (Forall "n" Integer
         -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a.
Proposition a =>
SMTConfig -> String -> a -> [ProofObj] -> TP (Proof a)
lemmaWith SMTConfig
cvc5 String
"drop_append"
                        (\(Forall SBV Integer
n) (Forall SList a
xs) (Forall SList a
ys) -> SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n (SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys) SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n SList a
xs SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV Integer -> SList a -> SList a
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop (SBV Integer
n SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
- SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
xs) SList a
ys)
                        []

-- | @length xs == length ys ==> map fst (zip xs ys) = xs@
--
-- >>> runTP $ map_fst_zip @Integer @Integer
-- Inductive lemma: map_fst_zip
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] map_fst_zip :: (Ɐxs ∷ [Integer], Ɐys ∷ [Integer]) → Bool
map_fst_zip :: forall a b. (SymVal a, SymVal b) => TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
map_fst_zip :: forall a b.
(SymVal a, SymVal b) =>
TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
map_fst_zip = String
-> ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
-> (Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
    -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
    -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) [a])
-> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
forall t.
(Proposition ((Forall "xs" [a], Forall "ys" [b]) -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
-> (Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
    -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
    -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) t)
-> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"map_fst_zip"
                     (\(Forall SBV [a]
xs, Forall SBV [b]
ys) -> SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [b] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [b]
ys SBool -> SBool -> SBool
.=> (STuple a b -> SBV a) -> SList (a, b) -> SBV [a]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV a
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys) SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [a]
xs) ((Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
  -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
  -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) [a])
 -> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool)))
-> (Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
    -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
    -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) [a])
-> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
forall a b. (a -> b) -> a -> b
$
                     \Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
ih (SBV a
x, SBV [a]
xs, SBV b
y, SBV [b]
ys) -> [SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [b] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [b]
ys)]
                                        [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (STuple a b -> SBV a) -> SList (a, b) -> SBV [a]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV a
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) (SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [b]
ys))
                                        SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (STuple a b -> SBV a) -> SList (a, b) -> SBV [a]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV a
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst ((SBV a, SBV b) -> STuple a b
forall tup a. Tuple tup a => a -> SBV tup
tuple (SBV a
x, SBV b
y) STuple a b -> SList (a, b) -> SList (a, b)
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys)
                                        SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: STuple a b -> SBV a
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst ((SBV a, SBV b) -> STuple a b
forall tup a. Tuple tup a => a -> SBV tup
tuple (SBV a
x, SBV b
y)) SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (STuple a b -> SBV a) -> SList (a, b) -> SBV [a]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV a
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys)
                                        SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (STuple a b -> SBV a) -> SList (a, b) -> SBV [a]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV a
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys)
                                        SBV [a] -> Proof SBool -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
ih
                                        TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs
                                        SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed

-- | @length xs == length ys ==> map snd (zip xs ys) = xs@
--
-- >>> runTP $ map_snd_zip @Integer @Integer
-- Inductive lemma: map_snd_zip
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] map_snd_zip :: (Ɐxs ∷ [Integer], Ɐys ∷ [Integer]) → Bool
map_snd_zip :: forall a b. (SymVal a, SymVal b) => TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
map_snd_zip :: forall a b.
(SymVal a, SymVal b) =>
TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
map_snd_zip = String
-> ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
-> (Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
    -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
    -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) [b])
-> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
forall t.
(Proposition ((Forall "xs" [a], Forall "ys" [b]) -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
-> (Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
    -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
    -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) t)
-> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"map_snd_zip"
                     (\(Forall SBV [a]
xs, Forall SBV [b]
ys) -> SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [b] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [b]
ys SBool -> SBool -> SBool
.=> (STuple a b -> SBV b) -> SList (a, b) -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV b
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys) SBV [b] -> SBV [b] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [b]
ys) ((Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
  -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
  -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) [b])
 -> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool)))
-> (Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
    -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
    -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) [b])
-> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
forall a b. (a -> b) -> a -> b
$
                     \Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
ih (SBV a
x, SBV [a]
xs, SBV b
y, SBV [b]
ys) -> [SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [b] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [b]
ys)]
                                        [SBool] -> TPProofRaw (SBV [b]) -> (SBool, TPProofRaw (SBV [b]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (STuple a b -> SBV b) -> SList (a, b) -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV b
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) (SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [b]
ys))
                                        SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (STuple a b -> SBV b) -> SList (a, b) -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV b
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd ((SBV a, SBV b) -> STuple a b
forall tup a. Tuple tup a => a -> SBV tup
tuple (SBV a
x, SBV b
y) STuple a b -> SList (a, b) -> SList (a, b)
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys)
                                        SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: STuple a b -> SBV b
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd ((SBV a, SBV b) -> STuple a b
forall tup a. Tuple tup a => a -> SBV tup
tuple (SBV a
x, SBV b
y)) SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (STuple a b -> SBV b) -> SList (a, b) -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV b
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys)
                                        SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (STuple a b -> SBV b) -> SList (a, b) -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV b
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys)
                                        SBV [b] -> Proof SBool -> Hinted (SBV [b])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
ih
                                        TPProofRaw (SBV [b])
-> ChainsTo (TPProofRaw (SBV [b]))
-> ChainsTo (TPProofRaw (SBV [b]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [b]
ys
                                        SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [b])
TPProofRaw (SBV [b])
forall a. TPProofRaw a
qed

-- | @map fst (zip xs ys) == take (min (length xs) (length ys)) xs@
--
-- >>> runTP $ map_fst_zip_take @Integer @Integer
-- Lemma: take_cons                        Q.E.D.
-- Inductive lemma: map_fst_zip_take
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] map_fst_zip_take :: (Ɐxs ∷ [Integer], Ɐys ∷ [Integer]) → Bool
map_fst_zip_take :: forall a b. (SymVal a, SymVal b) => TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
map_fst_zip_take :: forall a b.
(SymVal a, SymVal b) =>
TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
map_fst_zip_take = do
   Proof
  (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
tc <- forall a.
SymVal a =>
TP
  (Proof
     (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool))
take_cons @a

   String
-> ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
-> (Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
    -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
    -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) [a])
-> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
forall t.
(Proposition ((Forall "xs" [a], Forall "ys" [b]) -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
-> (Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
    -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
    -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) t)
-> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"map_fst_zip_take"
          (\(Forall SBV [a]
xs, Forall SBV [b]
ys) -> (STuple a b -> SBV a) -> SList (a, b) -> SBV [a]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV a
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys) SBV [a] -> SBV [a] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smin` SBV [b] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [b]
ys) SBV [a]
xs) ((Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
  -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
  -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) [a])
 -> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool)))
-> (Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
    -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
    -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) [a])
-> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
ih (SBV a
x, SBV [a]
xs, SBV b
y, SBV [b]
ys) -> [] [SBool] -> TPProofRaw (SBV [a]) -> (SBool, TPProofRaw (SBV [a]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (STuple a b -> SBV a) -> SList (a, b) -> SBV [a]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV a
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) (SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [b]
ys))
                                   SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (STuple a b -> SBV a) -> SList (a, b) -> SBV [a]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV a
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst ((SBV a, SBV b) -> STuple a b
forall tup a. Tuple tup a => a -> SBV tup
tuple (SBV a
x, SBV b
y) STuple a b -> SList (a, b) -> SList (a, b)
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys)
                                   SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (STuple a b -> SBV a) -> SList (a, b) -> SBV [a]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV a
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV a
fst (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys)
                                   SBV [a] -> Proof SBool -> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
ih
                                   TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smin` SBV [b] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [b]
ys) SBV [a]
xs
                                   SBV [a]
-> Proof
     (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
-> Hinted (SBV [a])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
tc
                                   TPProofRaw (SBV [a])
-> ChainsTo (TPProofRaw (SBV [a]))
-> ChainsTo (TPProofRaw (SBV [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ (SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smin` SBV [b] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [b]
ys)) (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                   SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smin` SBV [b] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [b]
ys)) (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                                   SBV [a] -> ChainsTo (SBV [a]) -> ChainsTo (SBV [a])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [a])
TPProofRaw (SBV [a])
forall a. TPProofRaw a
qed

-- | @map snd (zip xs ys) == take (min (length xs) (length ys)) xs@
--
-- >>> runTP $ map_snd_zip_take @Integer @Integer
-- Lemma: take_cons                        Q.E.D.
-- Inductive lemma: map_snd_zip_take
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4                               Q.E.D.
--   Step: 5                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] map_snd_zip_take :: (Ɐxs ∷ [Integer], Ɐys ∷ [Integer]) → Bool
map_snd_zip_take :: forall a b. (SymVal a, SymVal b) => TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
map_snd_zip_take :: forall a b.
(SymVal a, SymVal b) =>
TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
map_snd_zip_take = do
   Proof
  (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
tc <- forall a.
SymVal a =>
TP
  (Proof
     (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool))
take_cons @a

   String
-> ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
-> (Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
    -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
    -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) [b])
-> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
forall t.
(Proposition ((Forall "xs" [a], Forall "ys" [b]) -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
-> (Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
    -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
    -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) t)
-> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"map_snd_zip_take"
          (\(Forall SBV [a]
xs, Forall SBV [b]
ys) -> (STuple a b -> SBV b) -> SList (a, b) -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV b
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys) SBV [b] -> SBV [b] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smin` SBV [b] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [b]
ys) SBV [b]
ys) ((Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
  -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
  -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) [b])
 -> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool)))
-> (Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
    -> IHArg ((Forall "xs" [a], Forall "ys" [b]) -> SBool)
    -> IStepArgs ((Forall "xs" [a], Forall "ys" [b]) -> SBool) [b])
-> TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
ih (SBV a
x, SBV [a]
xs, SBV b
y, SBV [b]
ys) -> [] [SBool] -> TPProofRaw (SBV [b]) -> (SBool, TPProofRaw (SBV [b]))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- (STuple a b -> SBV b) -> SList (a, b) -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV b
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) (SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [b]
ys))
                                   SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (STuple a b -> SBV b) -> SList (a, b) -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV b
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd ((SBV a, SBV b) -> STuple a b
forall tup a. Tuple tup a => a -> SBV tup
tuple (SBV a
x, SBV b
y) STuple a b -> SList (a, b) -> SList (a, b)
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys)
                                   SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (STuple a b -> SBV b) -> SList (a, b) -> SBV [b]
forall func a b. SMap func a b => func -> SList a -> SList b
map STuple a b -> SBV b
forall a b. (SymVal a, SymVal b) => STuple a b -> SBV b
snd (SBV [a] -> SBV [b] -> SList (a, b)
forall a b.
(SymVal a, SymVal b) =>
SList a -> SList b -> SList (a, b)
zip SBV [a]
xs SBV [b]
ys)
                                   SBV [b] -> Proof SBool -> Hinted (SBV [b])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof SBool
Proof (IHType ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
ih
                                   TPProofRaw (SBV [b])
-> ChainsTo (TPProofRaw (SBV [b]))
-> ChainsTo (TPProofRaw (SBV [b]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV Integer -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smin` SBV [b] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [b]
ys) SBV [b]
ys
                                   SBV [b]
-> Proof
     (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
-> Hinted (SBV [b])
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool)
tc
                                   TPProofRaw (SBV [b])
-> ChainsTo (TPProofRaw (SBV [b]))
-> ChainsTo (TPProofRaw (SBV [b]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ (SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smin` SBV [b] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [b]
ys)) (SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [b]
ys)
                                   SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take (SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV Integer -> SBV Integer -> SBV Integer
forall a. OrdSymbolic a => a -> a -> a
`smin` SBV [b] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [b]
ys)) (SBV b
y SBV b -> SBV [b] -> SBV [b]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [b]
ys)
                                   SBV [b] -> ChainsTo (SBV [b]) -> ChainsTo (SBV [b])
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV [b])
TPProofRaw (SBV [b])
forall a. TPProofRaw a
qed

-- | Count the number of occurrences of an element in a list
count :: SymVal a => SBV a -> SList a -> SInteger
count :: forall a. SymVal a => SBV a -> SList a -> SBV Integer
count = String
-> (SBV a -> SList a -> SBV Integer)
-> SBV a
-> SList a
-> SBV Integer
forall a.
(SMTDefinable a, Typeable a, Lambda Symbolic a) =>
String -> a -> a
smtFunction String
"count" ((SBV a -> SList a -> SBV Integer)
 -> SBV a -> SList a -> SBV Integer)
-> (SBV a -> SList a -> SBV Integer)
-> SBV a
-> SList a
-> SBV Integer
forall a b. (a -> b) -> a -> b
$ \SBV a
e SList a
l -> SBool -> SBV Integer -> SBV Integer -> SBV Integer
forall a. Mergeable a => SBool -> a -> a -> a
ite (SList a -> SBool
forall a. SymVal a => SList a -> SBool
null SList a
l)
                                          SBV Integer
0
                                          (let (SBV a
x, SList a
xs) = SList a -> (SBV a, SList a)
forall a. SymVal a => SList a -> (SBV a, SList a)
uncons SList a
l
                                               cxs :: SBV Integer
cxs     = SBV a -> SList a -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SList a
xs
                                           in SBool -> SBV Integer -> SBV Integer -> SBV Integer
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a
e SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x) (SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV Integer
cxs) SBV Integer
cxs)

-- | Interleave the elements of two lists. If one ends, we take the rest from the other.
interleave :: SymVal a => SList a -> SList a -> SList a
interleave :: forall a. SymVal a => SList a -> SList a -> SList a
interleave = String
-> (SList a -> SList a -> SList a) -> SList a -> SList a -> SList a
forall a.
(SMTDefinable a, Typeable a, Lambda Symbolic a) =>
String -> a -> a
smtFunction String
"interleave" (\SList a
xs SList a
ys -> SBool -> SList a -> SList a -> SList a
forall a. Mergeable a => SBool -> a -> a -> a
ite (SList a -> SBool
forall a. SymVal a => SList a -> SBool
null  SList a
xs) SList a
ys (SList a -> SBV a
forall a. SymVal a => SList a -> SBV a
head SList a
xs SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
interleave SList a
ys (SList a -> SList a
forall a. SymVal a => SList a -> SList a
tail SList a
xs)))

-- | Prove that interleave preserves total length.
--
-- The induction here is on the total length of the lists, and hence
-- we use the generalized induction principle. We have:
--
-- >>> runTP $ interleaveLen @Integer
-- Inductive lemma (strong): interleaveLen
--   Step: Measure is non-negative         Q.E.D.
--   Step: 1 (2 way full case split)
--     Step: 1.1                           Q.E.D.
--     Step: 1.2.1                         Q.E.D.
--     Step: 1.2.2                         Q.E.D.
--     Step: 1.2.3                         Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] interleaveLen :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
interleaveLen :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
interleaveLen :: forall a.
SymVal a =>
TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
interleaveLen = String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> MeasureArgs
     (Forall "xs" [a] -> Forall "ys" [a] -> SBool) Integer
-> (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> StepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) Bool)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a m t.
(SInductive a, Proposition a, Zero m, SymVal t,
 EqSymbolic (SBV t)) =>
String
-> a
-> MeasureArgs a m
-> (Proof a -> StepArgs a t)
-> TP (Proof a)
forall m t.
(Proposition (Forall "xs" [a] -> Forall "ys" [a] -> SBool), Zero m,
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> MeasureArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) m
-> (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> StepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
sInduct String
"interleaveLen"
                        (\(Forall SBV [a]
xs) (Forall SBV [a]
ys) -> SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
ys SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
interleave SBV [a]
xs SBV [a]
ys))
                        (\SBV [a]
xs SBV [a]
ys -> SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
ys) ((Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
  -> StepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) Bool)
 -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)))
-> (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
    -> StepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) Bool)
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
                        \Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
ih SBV [a]
xs SBV [a]
ys -> [] [SBool] -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
ys SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
interleave SBV [a]
xs SBV [a]
ys)
                                        SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV [a]
-> TPProofRaw SBool
-> (SBV a -> SBV [a] -> TPProofRaw SBool)
-> TPProofRaw SBool
forall a r.
SymVal a =>
SList a
-> TPProofRaw r
-> (SBV a -> SList a -> TPProofRaw r)
-> TPProofRaw r
split SBV [a]
xs
                                                 TPProofRaw SBool
forall a. Trivial a => a
trivial
                                                 (\SBV a
a SBV [a]
as -> SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as) SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
ys SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
interleave (SBV a
a SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
as) SBV [a]
ys)
                                                        SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
as SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SBV [a]
ys SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV [a] -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length (SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
interleave SBV [a]
ys SBV [a]
as)
                                                        SBool -> Proof Bool -> Hinted SBool
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
ih Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> IArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"xs" SBV [a]
ys, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"ys" SBV [a]
as)
                                                        TPProofRaw SBool
-> ChainsTo (TPProofRaw SBool) -> ChainsTo (TPProofRaw SBool)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool
sTrue
                                                        SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo SBool
TPProofRaw SBool
forall a. TPProofRaw a
qed)

-- | Uninterleave the elements of two lists. We roughly split it into two, of alternating elements.
uninterleave :: SymVal a => SList a -> STuple [a] [a]
uninterleave :: forall a. SymVal a => SList a -> STuple [a] [a]
uninterleave SList a
lst = SList a -> STuple [a] [a] -> STuple [a] [a]
forall a. SymVal a => SList a -> STuple [a] [a] -> STuple [a] [a]
uninterleaveGen SList a
lst ((SList a, SList a) -> STuple [a] [a]
forall tup a. Tuple tup a => a -> SBV tup
tuple (SList a
forall a. SymVal a => SList a
nil, SList a
forall a. SymVal a => SList a
nil))

-- | Generalized form of uninterleave with the auxilary lists made explicit.
uninterleaveGen :: SymVal a => SList a -> STuple [a] [a] -> STuple [a] [a]
uninterleaveGen :: forall a. SymVal a => SList a -> STuple [a] [a] -> STuple [a] [a]
uninterleaveGen = String
-> (SList a -> STuple [a] [a] -> STuple [a] [a])
-> SList a
-> STuple [a] [a]
-> STuple [a] [a]
forall a.
(SMTDefinable a, Typeable a, Lambda Symbolic a) =>
String -> a -> a
smtFunction String
"uninterleave" (\SList a
xs STuple [a] [a]
alts -> let (SList a
es, SList a
os) = STuple [a] [a] -> (SList a, SList a)
forall tup a. Tuple tup a => SBV tup -> a
untuple STuple [a] [a]
alts
                                                          in SBool -> STuple [a] [a] -> STuple [a] [a] -> STuple [a] [a]
forall a. Mergeable a => SBool -> a -> a -> a
ite (SList a -> SBool
forall a. SymVal a => SList a -> SBool
null SList a
xs)
                                                                 ((SList a, SList a) -> STuple [a] [a]
forall tup a. Tuple tup a => a -> SBV tup
tuple (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
es, SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
os))
                                                                 (SList a -> STuple [a] [a] -> STuple [a] [a]
forall a. SymVal a => SList a -> STuple [a] [a] -> STuple [a] [a]
uninterleaveGen (SList a -> SList a
forall a. SymVal a => SList a -> SList a
tail SList a
xs) ((SList a, SList a) -> STuple [a] [a]
forall tup a. Tuple tup a => a -> SBV tup
tuple (SList a
os, SList a -> SBV a
forall a. SymVal a => SList a -> SBV a
head SList a
xs SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
es))))

-- | The functions 'uninterleave' and 'interleave' are inverses so long as the inputs are of the same length. (The equality
-- would even hold if the first argument has one extra element, but we keep things simple here.)
--
-- We have:
--
-- >>> runTP $ interleaveRoundTrip @Integer
-- Lemma: revCons                          Q.E.D.
-- Inductive lemma (strong): roundTripGen
--   Step: Measure is non-negative         Q.E.D.
--   Step: 1 (4 way full case split)
--     Step: 1.1                           Q.E.D.
--     Step: 1.2                           Q.E.D.
--     Step: 1.3                           Q.E.D.
--     Step: 1.4.1                         Q.E.D.
--     Step: 1.4.2                         Q.E.D.
--     Step: 1.4.3                         Q.E.D.
--     Step: 1.4.4                         Q.E.D.
--     Step: 1.4.5                         Q.E.D.
--     Step: 1.4.6                         Q.E.D.
--     Step: 1.4.7                         Q.E.D.
--     Step: 1.4.8                         Q.E.D.
--   Result:                               Q.E.D.
-- Lemma: interleaveRoundTrip
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] interleaveRoundTrip :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
interleaveRoundTrip :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
interleaveRoundTrip :: forall a.
SymVal a =>
TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
interleaveRoundTrip = do

   Proof (Forall "a" a -> Forall "as" [a] -> Forall "bs" [a] -> SBool)
revHelper <- String
-> (Forall "a" a -> Forall "as" [a] -> Forall "bs" [a] -> SBool)
-> [ProofObj]
-> TP
     (Proof
        (Forall "a" a -> Forall "as" [a] -> Forall "bs" [a] -> SBool))
forall a.
Proposition a =>
String -> a -> [ProofObj] -> TP (Proof a)
lemma String
"revCons" (\(Forall SBV a
a) (Forall SList a
as) (Forall SList a
bs) -> forall a. SymVal a => SList a -> SList a
reverse @a (SBV a
a SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
as) SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
bs SList a -> SList a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
as SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a
a SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
bs)) []

   -- Generalize the theorem first to take the helper lists explicitly
   Proof
  (Forall "xs" [a]
   -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
roundTripGen <- SMTConfig
-> String
-> (Forall "xs" [a]
    -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
-> MeasureArgs
     (Forall "xs" [a]
      -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
     Integer
-> (Proof
      (Forall "xs" [a]
       -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
    -> StepArgs
         (Forall "xs" [a]
          -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
         ([a], [a]))
-> TP
     (Proof
        (Forall "xs" [a]
         -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool))
forall a m t.
(SInductive a, Proposition a, Zero m, SymVal t,
 EqSymbolic (SBV t)) =>
SMTConfig
-> String
-> a
-> MeasureArgs a m
-> (Proof a -> StepArgs a t)
-> TP (Proof a)
forall m t.
(Proposition
   (Forall "xs" [a]
    -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool),
 Zero m, SymVal t, EqSymbolic (SBV t)) =>
SMTConfig
-> String
-> (Forall "xs" [a]
    -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
-> MeasureArgs
     (Forall "xs" [a]
      -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
     m
-> (Proof
      (Forall "xs" [a]
       -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
    -> StepArgs
         (Forall "xs" [a]
          -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
         t)
-> TP
     (Proof
        (Forall "xs" [a]
         -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool))
sInductWith SMTConfig
cvc5
         String
"roundTripGen"
         (\(Forall @"xs" SList a
xs) (Forall @"ys" SList a
ys) (Forall @"alts" SBV ([a], [a])
alts) ->
               SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
xs SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
ys SBool -> SBool -> SBool
.=> let (SList a
es, SList a
os) = SBV ([a], [a]) -> (SList a, SList a)
forall tup a. Tuple tup a => SBV tup -> a
untuple SBV ([a], [a])
alts
                                           in SList a -> SBV ([a], [a]) -> SBV ([a], [a])
forall a. SymVal a => SList a -> STuple [a] [a] -> STuple [a] [a]
uninterleaveGen (SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
interleave SList a
xs SList a
ys) SBV ([a], [a])
alts SBV ([a], [a]) -> SBV ([a], [a]) -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SList a, SList a) -> SBV ([a], [a])
forall tup a. Tuple tup a => a -> SBV tup
tuple (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
es SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
xs, SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
os SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys))
         (\SList a
xs SList a
ys SBV ([a], [a])
_alts -> SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
ys) ((Proof
    (Forall "xs" [a]
     -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
  -> StepArgs
       (Forall "xs" [a]
        -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
       ([a], [a]))
 -> TP
      (Proof
         (Forall "xs" [a]
          -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)))
-> (Proof
      (Forall "xs" [a]
       -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
    -> StepArgs
         (Forall "xs" [a]
          -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
         ([a], [a]))
-> TP
     (Proof
        (Forall "xs" [a]
         -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool))
forall a b. (a -> b) -> a -> b
$
         \Proof
  (Forall "xs" [a]
   -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
ih SList a
xs SList a
ys SBV ([a], [a])
alts -> [SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
xs SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
ys]
                        [SBool]
-> TPProofRaw (SBV ([a], [a]))
-> (SBool, TPProofRaw (SBV ([a], [a])))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- let (SList a
es, SList a
os) = SBV ([a], [a]) -> (SList a, SList a)
forall tup a. Tuple tup a => SBV tup -> a
untuple SBV ([a], [a])
alts
                        in SList a -> SBV ([a], [a]) -> SBV ([a], [a])
forall a. SymVal a => SList a -> STuple [a] [a] -> STuple [a] [a]
uninterleaveGen (SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
interleave SList a
xs SList a
ys) SBV ([a], [a])
alts
                        SBV ([a], [a])
-> ChainsTo (SBV ([a], [a])) -> ChainsTo (SBV ([a], [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SList a, SList a)
-> TPProofRaw (SBV ([a], [a]))
-> ((SBV a, SList a) -> TPProofRaw (SBV ([a], [a])))
-> ((SBV a, SList a) -> TPProofRaw (SBV ([a], [a])))
-> ((SBV a, SList a)
    -> (SBV a, SList a) -> TPProofRaw (SBV ([a], [a])))
-> TPProofRaw (SBV ([a], [a]))
forall a b r.
(SymVal a, SymVal b) =>
(SList a, SList b)
-> TPProofRaw r
-> ((SBV b, SList b) -> TPProofRaw r)
-> ((SBV a, SList a) -> TPProofRaw r)
-> ((SBV a, SList a) -> (SBV b, SList b) -> TPProofRaw r)
-> TPProofRaw r
split2 (SList a
xs, SList a
ys)
                                  TPProofRaw (SBV ([a], [a]))
forall a. Trivial a => a
trivial
                                  (SBV a, SList a) -> TPProofRaw (SBV ([a], [a]))
forall a. Trivial a => a
trivial
                                  (SBV a, SList a) -> TPProofRaw (SBV ([a], [a]))
forall a. Trivial a => a
trivial
                                  (\(SBV a
a, SList a
as) (SBV a
b, SList a
bs) -> SList a -> SBV ([a], [a]) -> SBV ([a], [a])
forall a. SymVal a => SList a -> STuple [a] [a] -> STuple [a] [a]
uninterleaveGen (SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
interleave (SBV a
a SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
as) (SBV a
b SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
bs)) SBV ([a], [a])
alts
                                                    SBV ([a], [a])
-> ChainsTo (SBV ([a], [a])) -> ChainsTo (SBV ([a], [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SList a -> SBV ([a], [a]) -> SBV ([a], [a])
forall a. SymVal a => SList a -> STuple [a] [a] -> STuple [a] [a]
uninterleaveGen (SBV a
a SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
interleave (SBV a
b SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
bs) SList a
as) SBV ([a], [a])
alts
                                                    SBV ([a], [a])
-> ChainsTo (SBV ([a], [a])) -> ChainsTo (SBV ([a], [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SList a -> SBV ([a], [a]) -> SBV ([a], [a])
forall a. SymVal a => SList a -> STuple [a] [a] -> STuple [a] [a]
uninterleaveGen (SBV a
a SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV a
b SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
interleave SList a
as SList a
bs) SBV ([a], [a])
alts
                                                    SBV ([a], [a])
-> ChainsTo (SBV ([a], [a])) -> ChainsTo (SBV ([a], [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SList a -> SBV ([a], [a]) -> SBV ([a], [a])
forall a. SymVal a => SList a -> STuple [a] [a] -> STuple [a] [a]
uninterleaveGen (SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
interleave SList a
as SList a
bs) ((SList a, SList a) -> SBV ([a], [a])
forall tup a. Tuple tup a => a -> SBV tup
tuple (SBV a
a SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
es, SBV a
b SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
os))
                                                    SBV ([a], [a]) -> Proof Bool -> Hinted (SBV ([a], [a]))
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (Forall "xs" [a]
   -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
ih Proof
  (Forall "xs" [a]
   -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
-> IArgs
     (Forall "xs" [a]
      -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
-> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"xs" SList a
as, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"ys" SList a
bs, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"alts" ((SList a, SList a) -> SBV ([a], [a])
forall tup a. Tuple tup a => a -> SBV tup
tuple (SBV a
a SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
es, SBV a
b SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
os)))
                                                    TPProofRaw (SBV ([a], [a]))
-> ChainsTo (TPProofRaw (SBV ([a], [a])))
-> ChainsTo (TPProofRaw (SBV ([a], [a])))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SList a, SList a) -> SBV ([a], [a])
forall tup a. Tuple tup a => a -> SBV tup
tuple (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse (SBV a
a SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
es) SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
as, SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse (SBV a
b SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
os) SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
bs)
                                                    SBV ([a], [a]) -> Proof Bool -> Hinted (SBV ([a], [a]))
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "a" a -> Forall "as" [a] -> Forall "bs" [a] -> SBool)
revHelper Proof (Forall "a" a -> Forall "as" [a] -> Forall "bs" [a] -> SBool)
-> IArgs
     (Forall "a" a -> Forall "as" [a] -> Forall "bs" [a] -> SBool)
-> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"a" SBV a
a, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"as" SList a
es, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"bs" SList a
as)
                                                    TPProofRaw (SBV ([a], [a]))
-> ChainsTo (TPProofRaw (SBV ([a], [a])))
-> ChainsTo (TPProofRaw (SBV ([a], [a])))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SList a, SList a) -> SBV ([a], [a])
forall tup a. Tuple tup a => a -> SBV tup
tuple (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
es SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a
a SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
as), SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse (SBV a
b SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
os) SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
bs)
                                                    SBV ([a], [a]) -> Proof Bool -> Hinted (SBV ([a], [a]))
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "a" a -> Forall "as" [a] -> Forall "bs" [a] -> SBool)
revHelper Proof (Forall "a" a -> Forall "as" [a] -> Forall "bs" [a] -> SBool)
-> IArgs
     (Forall "a" a -> Forall "as" [a] -> Forall "bs" [a] -> SBool)
-> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"a" SBV a
b, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"as" SList a
os, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"bs" SList a
bs)
                                                    TPProofRaw (SBV ([a], [a]))
-> ChainsTo (TPProofRaw (SBV ([a], [a])))
-> ChainsTo (TPProofRaw (SBV ([a], [a])))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SList a, SList a) -> SBV ([a], [a])
forall tup a. Tuple tup a => a -> SBV tup
tuple (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
es SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a
a SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
as), SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
os SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ (SBV a
b SBV a -> SList a -> SList a
forall a. SymVal a => SBV a -> SList a -> SList a
.: SList a
bs))
                                                    SBV ([a], [a])
-> ChainsTo (SBV ([a], [a])) -> ChainsTo (SBV ([a], [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SList a, SList a) -> SBV ([a], [a])
forall tup a. Tuple tup a => a -> SBV tup
tuple (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
es SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
xs, SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
os SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys)
                                                    SBV ([a], [a])
-> ChainsTo (SBV ([a], [a])) -> ChainsTo (SBV ([a], [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV ([a], [a]))
TPProofRaw (SBV ([a], [a]))
forall a. TPProofRaw a
qed)

   -- Round-trip theorem:
   String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> StepArgs
     (Forall "xs" [a] -> Forall "ys" [a] -> SBool) ([a], [a])
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "ys" [a] -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "ys" [a] -> SBool)
-> StepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) t
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a t.
(Calc a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String -> a -> StepArgs a t -> TP (Proof a)
calc String
"interleaveRoundTrip"
           (\(Forall SList a
xs) (Forall SList a
ys) -> SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
xs SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
ys SBool -> SBool -> SBool
.=> SList a -> SBV ([a], [a])
forall a. SymVal a => SList a -> STuple [a] [a]
uninterleave (SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
interleave SList a
xs SList a
ys) SBV ([a], [a]) -> SBV ([a], [a]) -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== (SList a, SList a) -> SBV ([a], [a])
forall tup a. Tuple tup a => a -> SBV tup
tuple (SList a
xs, SList a
ys)) (StepArgs (Forall "xs" [a] -> Forall "ys" [a] -> SBool) ([a], [a])
 -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool)))
-> StepArgs
     (Forall "xs" [a] -> Forall "ys" [a] -> SBool) ([a], [a])
-> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
forall a b. (a -> b) -> a -> b
$
           \SList a
xs SList a
ys -> [SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
xs SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SList a -> SBV Integer
forall a. SymVal a => SList a -> SBV Integer
length SList a
ys]
                  [SBool]
-> TPProofRaw (SBV ([a], [a]))
-> (SBool, TPProofRaw (SBV ([a], [a])))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SList a -> SBV ([a], [a])
forall a. SymVal a => SList a -> STuple [a] [a]
uninterleave (SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
interleave SList a
xs SList a
ys)
                  SBV ([a], [a])
-> ChainsTo (SBV ([a], [a])) -> ChainsTo (SBV ([a], [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SList a -> SBV ([a], [a]) -> SBV ([a], [a])
forall a. SymVal a => SList a -> STuple [a] [a] -> STuple [a] [a]
uninterleaveGen (SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
interleave SList a
xs SList a
ys) ((SList a, SList a) -> SBV ([a], [a])
forall tup a. Tuple tup a => a -> SBV tup
tuple (SList a
forall a. SymVal a => SList a
nil, SList a
forall a. SymVal a => SList a
nil))
                  SBV ([a], [a]) -> Proof Bool -> Hinted (SBV ([a], [a]))
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (Forall "xs" [a]
   -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
roundTripGen Proof
  (Forall "xs" [a]
   -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
-> IArgs
     (Forall "xs" [a]
      -> Forall "ys" [a] -> Forall "alts" ([a], [a]) -> SBool)
-> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"xs" SList a
xs, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"ys" SList a
ys, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"alts" ((SList a, SList a) -> SBV ([a], [a])
forall tup a. Tuple tup a => a -> SBV tup
tuple (SList a
forall a. SymVal a => SList a
nil, SList a
forall a. SymVal a => SList a
nil)))
                  TPProofRaw (SBV ([a], [a]))
-> ChainsTo (TPProofRaw (SBV ([a], [a])))
-> ChainsTo (TPProofRaw (SBV ([a], [a])))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (SList a, SList a) -> SBV ([a], [a])
forall tup a. Tuple tup a => a -> SBV tup
tuple (SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
forall a. SymVal a => SList a
nil SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
xs, SList a -> SList a
forall a. SymVal a => SList a -> SList a
reverse SList a
forall a. SymVal a => SList a
nil SList a -> SList a -> SList a
forall a. SymVal a => SList a -> SList a -> SList a
++ SList a
ys)
                  SBV ([a], [a])
-> ChainsTo (SBV ([a], [a])) -> ChainsTo (SBV ([a], [a]))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV ([a], [a]))
TPProofRaw (SBV ([a], [a]))
forall a. TPProofRaw a
qed

-- | @count e (xs ++ ys) == count e xs + count e ys@
--
-- >>> runTP $ countAppend @Integer
-- Inductive lemma: countAppend
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2 (unfold count)                Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4 (simplify)                    Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] countAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Ɐe ∷ Integer → Bool
countAppend :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool))
countAppend :: forall a.
SymVal a =>
TP
  (Proof
     (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool))
countAppend =
   String
-> (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)
-> (Proof
      (IHType
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool))
    -> IHArg
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)
    -> IStepArgs
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)
         Integer)
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool))
forall t.
(Proposition
   (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)
-> (Proof
      (IHType
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool))
    -> IHArg
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)
    -> IStepArgs
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool) t)
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"countAppend"
          (\(Forall SBV [a]
xs) (Forall SBV [a]
ys) (Forall SBV a
e) -> SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys) SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
ys) ((Proof
    (IHType
       (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool))
  -> IHArg
       (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)
  -> IStepArgs
       (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)
       Integer)
 -> TP
      (Proof
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)))
-> (Proof
      (IHType
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool))
    -> IHArg
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)
    -> IStepArgs
         (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)
         Integer)
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof
  (IHType
     (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool))
ih (SBV a
x, SBV [a]
xs) SBV [a]
ys SBV a
e -> [] [SBool]
-> TPProofRaw (SBV Integer) -> (SBool, TPProofRaw (SBV Integer))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e ((SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys)
                                 SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys))
                                 SBV Integer -> String -> Hinted (SBV Integer)
forall a b. HintsTo a b => a -> b -> Hinted a
?? String
"unfold count"
                                 TPProofRaw (SBV Integer)
-> ChainsTo (TPProofRaw (SBV Integer))
-> ChainsTo (TPProofRaw (SBV Integer))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (let r :: SBV Integer
r = SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e (SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV [a]
ys) in SBool -> SBV Integer -> SBV Integer -> SBV Integer
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a
e SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x) (SBV Integer
1SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+SBV Integer
r) SBV Integer
r)
                                 SBV Integer -> Proof Bool -> Hinted (SBV Integer)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof
  (IHType
     (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool))
Proof (Forall "ys" [a] -> Forall "e" a -> SBool)
ih Proof (Forall "ys" [a] -> Forall "e" a -> SBool)
-> IArgs (Forall "ys" [a] -> Forall "e" a -> SBool) -> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"ys" SBV [a]
ys, forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"e" SBV a
e)
                                 TPProofRaw (SBV Integer)
-> ChainsTo (TPProofRaw (SBV Integer))
-> ChainsTo (TPProofRaw (SBV Integer))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: (let r :: SBV Integer
r = SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
xs SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
ys in SBool -> SBV Integer -> SBV Integer -> SBV Integer
forall a. Mergeable a => SBool -> a -> a -> a
ite (SBV a
e SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x) (SBV Integer
1SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+SBV Integer
r) SBV Integer
r)
                                 SBV Integer -> String -> Hinted (SBV Integer)
forall a b. HintsTo a b => a -> b -> Hinted a
?? String
"simplify"
                                 TPProofRaw (SBV Integer)
-> ChainsTo (TPProofRaw (SBV Integer))
-> ChainsTo (TPProofRaw (SBV Integer))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
ys
                                 SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV Integer)
TPProofRaw (SBV Integer)
forall a. TPProofRaw a
qed

-- | @count e (take n xs) + count e (drop n xs) == count e xs@
--
-- >>> runTP $ takeDropCount @Integer
-- Inductive lemma: countAppend
--   Step: Base                            Q.E.D.
--   Step: 1                               Q.E.D.
--   Step: 2 (unfold count)                Q.E.D.
--   Step: 3                               Q.E.D.
--   Step: 4 (simplify)                    Q.E.D.
--   Result:                               Q.E.D.
-- Lemma: take_drop                        Q.E.D.
-- Lemma: takeDropCount
--   Step: 1                               Q.E.D.
--   Step: 2                               Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] takeDropCount :: Ɐxs ∷ [Integer] → Ɐn ∷ Integer → Ɐe ∷ Integer → Bool
takeDropCount :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool))
takeDropCount :: forall a.
SymVal a =>
TP
  (Proof
     (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool))
takeDropCount = do
       Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)
capp     <- forall a.
SymVal a =>
TP
  (Proof
     (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool))
countAppend @a
       Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool)
takeDrop <- forall a.
SymVal a =>
TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
take_drop   @a

       String
-> (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool)
-> StepArgs
     (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool)
     Integer
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool))
forall t.
(Proposition
   (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool),
 SymVal t, EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool)
-> StepArgs
     (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool) t
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool))
forall a t.
(Calc a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String -> a -> StepArgs a t -> TP (Proof a)
calc String
"takeDropCount"
            (\(Forall SBV [a]
xs) (Forall SBV Integer
n) (Forall SBV a
e) -> SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n SBV [a]
xs) SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n SBV [a]
xs) SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
xs) (StepArgs
   (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool)
   Integer
 -> TP
      (Proof
         (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool)))
-> StepArgs
     (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool)
     Integer
-> TP
     (Proof
        (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool))
forall a b. (a -> b) -> a -> b
$
            \SBV [a]
xs SBV Integer
n SBV a
e -> [] [SBool]
-> TPProofRaw (SBV Integer) -> (SBool, TPProofRaw (SBV Integer))
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n SBV [a]
xs) SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n SBV [a]
xs)
                          SBV Integer -> Proof Bool -> Hinted (SBV Integer)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)
capp Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)
-> IArgs
     (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool)
-> Proof Bool
forall a. Instantiatable a => Proof a -> IArgs a -> Proof Bool
`at` (forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"xs" (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n SBV [a]
xs), forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"ys" (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n SBV [a]
xs), forall (nm :: Symbol) a. SBV a -> Inst nm a
Inst @"e" SBV a
e)
                          TPProofRaw (SBV Integer)
-> ChainsTo (TPProofRaw (SBV Integer))
-> ChainsTo (TPProofRaw (SBV Integer))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e (SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
take SBV Integer
n SBV [a]
xs SBV [a] -> SBV [a] -> SBV [a]
forall a. SymVal a => SList a -> SList a -> SList a
++ SBV Integer -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV Integer -> SList a -> SList a
drop SBV Integer
n SBV [a]
xs)
                          SBV Integer
-> Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool)
-> Hinted (SBV Integer)
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool)
takeDrop
                          TPProofRaw (SBV Integer)
-> ChainsTo (TPProofRaw (SBV Integer))
-> ChainsTo (TPProofRaw (SBV Integer))
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
xs
                          SBV Integer -> ChainsTo (SBV Integer) -> ChainsTo (SBV Integer)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo (SBV Integer)
TPProofRaw (SBV Integer)
forall a. TPProofRaw a
qed

-- | @count e xs >= 0@
--
-- >>> runTP $ countNonNeg @Integer
-- Inductive lemma: countNonNeg
--   Step: Base                            Q.E.D.
--   Step: 1 (2 way case split)
--     Step: 1.1.1                         Q.E.D.
--     Step: 1.1.2                         Q.E.D.
--     Step: 1.2.1                         Q.E.D.
--     Step: 1.2.2                         Q.E.D.
--     Step: 1.Completeness                Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] countNonNeg :: Ɐxs ∷ [Integer] → Ɐe ∷ Integer → Bool
countNonNeg :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
countNonNeg :: forall a.
SymVal a =>
TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
countNonNeg =
   String
-> (Forall "xs" [a] -> Forall "e" a -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "e" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "e" a -> SBool) Bool)
-> TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "e" a -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "e" a -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "e" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "e" a -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"countNonNeg"
          (\(Forall SBV [a]
xs) (Forall SBV a
e) -> SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
xs SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= SBV Integer
0) ((Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "e" a -> SBool)
  -> IStepArgs (Forall "xs" [a] -> Forall "e" a -> SBool) Bool)
 -> TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "e" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "e" a -> SBool) Bool)
-> TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
forall a b. (a -> b) -> a -> b
$
          \Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
ih (SBV a
x, SBV [a]
xs) SBV a
e -> [] [SBool] -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= SBV Integer
0
                              SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBool, TPProofRaw SBool)] -> TPProofRaw SBool
forall a. [(SBool, TPProofRaw a)] -> TPProofRaw a
cases [ SBV a
e SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x SBool -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
xs SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= SBV Integer
0
                                                  SBool -> Proof (Forall "e" a -> SBool) -> Hinted SBool
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
Proof (Forall "e" a -> SBool)
ih
                                                  TPProofRaw SBool
-> ChainsTo (TPProofRaw SBool) -> ChainsTo (TPProofRaw SBool)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool
sTrue
                                                  SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo SBool
TPProofRaw SBool
forall a. TPProofRaw a
qed
                                       , SBV a
e SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
./= SBV a
x SBool -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
xs SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= SBV Integer
0
                                                  SBool -> Proof (Forall "e" a -> SBool) -> Hinted SBool
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
Proof (Forall "e" a -> SBool)
ih
                                                  TPProofRaw SBool
-> ChainsTo (TPProofRaw SBool) -> ChainsTo (TPProofRaw SBool)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool
sTrue
                                                  SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo SBool
TPProofRaw SBool
forall a. TPProofRaw a
qed
                                       ]

-- | @e \`elem\` xs ==> count e xs .> 0@
--
-- >>> runTP $ countElem @Integer
-- Inductive lemma: countNonNeg
--   Step: Base                            Q.E.D.
--   Step: 1 (2 way case split)
--     Step: 1.1.1                         Q.E.D.
--     Step: 1.1.2                         Q.E.D.
--     Step: 1.2.1                         Q.E.D.
--     Step: 1.2.2                         Q.E.D.
--     Step: 1.Completeness                Q.E.D.
--   Result:                               Q.E.D.
-- Inductive lemma: countElem
--   Step: Base                            Q.E.D.
--   Step: 1 (2 way case split)
--     Step: 1.1.1                         Q.E.D.
--     Step: 1.1.2                         Q.E.D.
--     Step: 1.2.1                         Q.E.D.
--     Step: 1.2.2                         Q.E.D.
--     Step: 1.Completeness                Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] countElem :: Ɐxs ∷ [Integer] → Ɐe ∷ Integer → Bool
countElem :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
countElem :: forall a.
(Eq a, SymVal a) =>
TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
countElem = do

    Proof (Forall "xs" [a] -> Forall "e" a -> SBool)
cnn <- forall a.
SymVal a =>
TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
countNonNeg @a

    String
-> (Forall "xs" [a] -> Forall "e" a -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "e" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "e" a -> SBool) Bool)
-> TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "e" a -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "e" a -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "e" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "e" a -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"countElem"
           (\(Forall SBV [a]
xs) (Forall SBV a
e) -> SBV a
e SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`elem` SBV [a]
xs SBool -> SBool -> SBool
.=> SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
xs SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0) ((Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "e" a -> SBool)
  -> IStepArgs (Forall "xs" [a] -> Forall "e" a -> SBool) Bool)
 -> TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "e" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "e" a -> SBool) Bool)
-> TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
forall a b. (a -> b) -> a -> b
$
           \Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
ih (SBV a
x, SBV [a]
xs) SBV a
e -> [SBV a
e SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`elem` (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)]
                         [SBool] -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs) SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0
                         SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBool, TPProofRaw SBool)] -> TPProofRaw SBool
forall a. [(SBool, TPProofRaw a)] -> TPProofRaw a
cases [ SBV a
e SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x SBool -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> SBV Integer
1 SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
xs SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0
                                             SBool
-> Proof (Forall "xs" [a] -> Forall "e" a -> SBool) -> Hinted SBool
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (Forall "xs" [a] -> Forall "e" a -> SBool)
cnn
                                             TPProofRaw SBool
-> ChainsTo (TPProofRaw SBool) -> ChainsTo (TPProofRaw SBool)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool
sTrue
                                             SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo SBool
TPProofRaw SBool
forall a. TPProofRaw a
qed
                                  , SBV a
e SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
./= SBV a
x SBool -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
xs SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0
                                             SBool -> Proof (Forall "e" a -> SBool) -> Hinted SBool
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
Proof (Forall "e" a -> SBool)
ih
                                             TPProofRaw SBool
-> ChainsTo (TPProofRaw SBool) -> ChainsTo (TPProofRaw SBool)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool
sTrue
                                             SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo SBool
TPProofRaw SBool
forall a. TPProofRaw a
qed
                                  ]

-- | @count e xs .> 0 .=> e \`elem\` xs@
--
-- >>> runTP $ elemCount @Integer
-- Inductive lemma: elemCount
--   Step: Base                            Q.E.D.
--   Step: 1 (2 way case split)
--     Step: 1.1                           Q.E.D.
--     Step: 1.2.1                         Q.E.D.
--     Step: 1.2.2                         Q.E.D.
--     Step: 1.Completeness                Q.E.D.
--   Result:                               Q.E.D.
-- [Proven] elemCount :: Ɐxs ∷ [Integer] → Ɐe ∷ Integer → Bool
elemCount :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
elemCount :: forall a.
(Eq a, SymVal a) =>
TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
elemCount =
    String
-> (Forall "xs" [a] -> Forall "e" a -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "e" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "e" a -> SBool) Bool)
-> TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
forall t.
(Proposition (Forall "xs" [a] -> Forall "e" a -> SBool), SymVal t,
 EqSymbolic (SBV t)) =>
String
-> (Forall "xs" [a] -> Forall "e" a -> SBool)
-> (Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "e" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "e" a -> SBool) t)
-> TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
forall a t.
(Inductive a, Proposition a, SymVal t, EqSymbolic (SBV t)) =>
String
-> a
-> (Proof (IHType a) -> IHArg a -> IStepArgs a t)
-> TP (Proof a)
induct String
"elemCount"
           (\(Forall SBV [a]
xs) (Forall SBV a
e) -> SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
xs SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0 SBool -> SBool -> SBool
.=> SBV a
e SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`elem` SBV [a]
xs) ((Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
  -> IHArg (Forall "xs" [a] -> Forall "e" a -> SBool)
  -> IStepArgs (Forall "xs" [a] -> Forall "e" a -> SBool) Bool)
 -> TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool)))
-> (Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
    -> IHArg (Forall "xs" [a] -> Forall "e" a -> SBool)
    -> IStepArgs (Forall "xs" [a] -> Forall "e" a -> SBool) Bool)
-> TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
forall a b. (a -> b) -> a -> b
$
           \Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
ih (SBV a
x, SBV [a]
xs) SBV a
e -> [SBV a -> SBV [a] -> SBV Integer
forall a. SymVal a => SBV a -> SList a -> SBV Integer
count SBV a
e SBV [a]
xs SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SBV Integer
0]
                         [SBool] -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
|- SBV a
e SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`elem` (SBV a
x SBV a -> SBV [a] -> SBV [a]
forall a. SymVal a => SBV a -> SList a -> SList a
.: SBV [a]
xs)
                         SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: [(SBool, TPProofRaw SBool)] -> TPProofRaw SBool
forall a. [(SBool, TPProofRaw a)] -> TPProofRaw a
cases [ SBV a
e SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV a
x SBool -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> TPProofRaw SBool
forall a. Trivial a => a
trivial
                                  , SBV a
e SBV a -> SBV a -> SBool
forall a. EqSymbolic a => a -> a -> SBool
./= SBV a
x SBool -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
forall a. SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
==> SBV a
e SBV a -> SBV [a] -> SBool
forall a. (Eq a, SymVal a) => SBV a -> SList a -> SBool
`elem` SBV [a]
xs
                                             SBool -> Proof (Forall "e" a -> SBool) -> Hinted SBool
forall a b. HintsTo a b => a -> b -> Hinted a
?? Proof (IHType (Forall "xs" [a] -> Forall "e" a -> SBool))
Proof (Forall "e" a -> SBool)
ih
                                             TPProofRaw SBool
-> ChainsTo (TPProofRaw SBool) -> ChainsTo (TPProofRaw SBool)
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: SBool
sTrue
                                             SBool -> ChainsTo SBool -> ChainsTo SBool
forall a. ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a
=: ChainsTo SBool
TPProofRaw SBool
forall a. TPProofRaw a
qed
                                  ]

{- HLint ignore revRev         "Redundant reverse" -}
{- HLint ignore allAny         "Use and"           -}
{- HLint ignore bookKeeping    "Fuse foldr/map"    -}
{- HLint ignore foldrMapFusion "Fuse foldr/map"    -}
{- HLint ignore filterConcat   "Move filter"       -}
{- HLint ignore module         "Use camelCase"     -}
{- HLint ignore module         "Use first"         -}
{- HLint ignore module         "Use second"        -}
{- HLint ignore module         "Use zipWith"       -}
{- HLint ignore mapCompose     "Use map once"      -}
{- HLint ignore tailsAppend    "Avoid lambda"      -}
{- HLint ignore tailsAppend    "Use :"             -}
{- HLint ignore mapReverse     "Evaluate"          -}
{- HLint ignore takeDropWhile  "Evaluate"          -}