diff --git a/libs/base/Control/WellFounded.idr b/libs/base/Control/WellFounded.idr index 04bc0edbb..27045206e 100644 --- a/libs/base/Control/WellFounded.idr +++ b/libs/base/Control/WellFounded.idr @@ -59,6 +59,20 @@ accInd : {0 rel : a -> a -> Type} -> {0 P : a -> Type} -> accInd step z (Access f) = step z $ \y, lt => accInd step y (f y lt) +||| Depedently-typed induction for creating extrinsic proofs on results of `accInd`. +export +accIndProp : {0 P : a -> Type} -> + (step : (x : a) -> ((y : a) -> rel y x -> P y) -> P x) -> + {0 RP : (x : a) -> P x -> Type} -> + (ih : (x : a) -> + (f : (y : a) -> rel y x -> P y) -> + ((y : a) -> (isRel : rel y x) -> RP y (f y isRel)) -> + RP x (step x f)) -> + (z : a) -> (0 acc : Accessible rel z) -> RP z (accInd step z acc) +accIndProp step ih z (Access rec) = + ih z (\y, lt => accInd step y (rec y lt)) + (\y, lt => accIndProp {RP} step ih y (rec y lt)) + ||| Simply-typed recursion based on well-founded-ness. ||| ||| This is `accRec` applied to accessibility derived from a `WellFounded` @@ -79,6 +93,19 @@ wfInd : (0 _ : WellFounded a rel) => {0 P : a -> Type} -> (myz : a) -> P myz wfInd step myz = accInd step myz (wellFounded {rel} myz) +||| Depedently-typed induction for creating extrinsic proofs on results of `wfInd`. +export +wfIndProp : (0 _ : WellFounded a rel) => + {0 P : a -> Type} -> + (step : (x : a) -> ((y : a) -> rel y x -> P y) -> P x) -> + {0 RP : (x : a) -> P x -> Type} -> + (ih : (x : a) -> + (f : (y : a) -> rel y x -> P y) -> + ((y : a) -> (isRel : rel y x) -> RP y (f y isRel)) -> + RP x (step x f)) -> + (myz : a) -> RP myz (wfInd step myz) +wfIndProp step ih myz = accIndProp {RP} step ih myz (wellFounded {rel} myz) + ||| Types that have a concept of size. The size must be a natural number. public export interface Sized a where diff --git a/libs/contrib/Data/List/Sufficient.idr b/libs/contrib/Data/List/Sufficient.idr index 8e6d3ea1c..e72c8173b 100644 --- a/libs/contrib/Data/List/Sufficient.idr +++ b/libs/contrib/Data/List/Sufficient.idr @@ -1,32 +1,23 @@ -||| 'Sufficient' lists: a structurally inductive view of lists xs -||| as given by xs = non-empty prefix + sufficient suffix -||| -||| Useful for termination arguments for function definitions -||| which provably consume a non-empty (but otherwise arbitrary) prefix -||| *without* having to resort to ancillary WF induction on length etc. -||| e.g. lexers, parsers etc. -||| -||| Credited by Conor McBride as originally due to James McKinna +||| WellFounded on List suffixes module Data.List.Sufficient -||| Sufficient view -public export -data Sufficient : (xs : List a) -> Type where - SuffAcc : {xs : List a} - -> (suff_ih : {x : a} -> {pre, suff : List a} - -> xs = x :: (pre ++ suff) - -> Sufficient suff) - -> Sufficient xs +import Control.WellFounded -||| Sufficient view covering property -export -sufficient : (xs : List a) -> Sufficient xs -sufficient [] = SuffAcc (\case _ impossible) -sufficient (x :: xs) with (sufficient xs) - sufficient (x :: xs) | suffxs@(SuffAcc suff_ih) - = SuffAcc (\case Refl => prf Refl) - where prf : {pre, suff : List a} - -> xs = pre ++ suff - -> Sufficient suff - prf {pre = []} Refl = suffxs - prf {pre = (y :: ys)} eq = suff_ih eq +%default total + +public export +data Suffix : (ys,xs : List a) -> Type where + IsSuffix : (x : a) -> (zs : List a) + -> (0 ford : xs = x :: zs ++ ys) -> Suffix ys xs + +SuffixAccessible : (xs : List a) -> Accessible Suffix xs +SuffixAccessible [] = Access (\y => \case (IsSuffix x zs _) impossible) +SuffixAccessible ws@(x :: xs) = + let fact1@(Access f) = SuffixAccessible xs + in Access $ \ys => \case + (IsSuffix x [] Refl) => fact1 + (IsSuffix x (z :: zs) Refl) => f ys (IsSuffix z zs Refl) + +public export +WellFounded (List a) Suffix where + wellFounded = SuffixAccessible