mirror of
https://github.com/idris-lang/Idris2.git
synced 2024-11-13 05:48:39 +03:00
Merge pull request #316 from ohad/fancy-preorder-reasoning
Fancy preorder reasoning
This commit is contained in:
commit
59588a3f3a
@ -33,36 +33,25 @@ length xs = length_aux xs Z
|
|||||||
|
|
||||||
export
|
export
|
||||||
length_ext : (xs : List a) -> Data.List.length xs = Data.List.TailRec.length xs
|
length_ext : (xs : List a) -> Data.List.length xs = Data.List.TailRec.length xs
|
||||||
length_ext xs = Calculate [
|
length_ext xs = Calc $
|
||||||
Data.List.length xs
|
|~ Data.List.length xs
|
||||||
==| sym (plusZeroRightNeutral (Data.List.length xs)),
|
~~ Data.List.length xs + 0 ...( sym $ plusZeroRightNeutral $ Data.List.length xs )
|
||||||
Data.List.length xs + 0
|
~~ Data.List.TailRec.length_aux xs 0 ...( lemma 0 xs )
|
||||||
==| lemma 0 xs,
|
~~ Data.List.TailRec.length xs ...( Refl )
|
||||||
Data.List.TailRec.length_aux xs 0
|
|
||||||
==| Refl,
|
|
||||||
Data.List.TailRec.length xs
|
|
||||||
==| QED
|
|
||||||
]
|
|
||||||
where
|
where
|
||||||
lemma : (n : Nat) -> (xs : List a) ->
|
lemma : (n : Nat) -> (xs : List a) ->
|
||||||
Data.List.length xs + n = length_aux xs n
|
Data.List.length xs + n = length_aux xs n
|
||||||
lemma n [] = Refl
|
lemma n [] = Refl
|
||||||
lemma n (_ :: xs) =
|
lemma n (_ :: xs) =
|
||||||
let length_xs : Nat
|
let length_xs : Nat
|
||||||
length_xs = Data.List.length xs in
|
length_xs = Data.List.length xs in
|
||||||
Calculate [
|
Calc $
|
||||||
1 + (length_xs + n)
|
|~ 1 + (length_xs + n)
|
||||||
-- Hopefully we could Frex these two steps one day
|
-- Hopefully we could Frex these two steps one day
|
||||||
==| plusAssociative 1 length_xs n ,
|
~~ (1 + length_xs) + n ...( plusAssociative 1 length_xs n )
|
||||||
(1 + length_xs) + n
|
~~ (length_xs + 1) + n ...( cong (+n) (plusCommutative 1 length_xs) )
|
||||||
==| cong (+n) (plusCommutative 1 length_xs) ,
|
~~ (length_xs) + (1 + n) ...( sym (plusAssociative length_xs 1 n) )
|
||||||
(length_xs + 1) + n
|
~~ length_aux xs (1 + n) ...( lemma (1 + n) xs )
|
||||||
==| sym (plusAssociative length_xs 1 n),
|
|
||||||
(length_xs) + (1 + n)
|
|
||||||
==| lemma (1 + n) xs,
|
|
||||||
length_aux xs (1 + n)
|
|
||||||
==| QED
|
|
||||||
]
|
|
||||||
|
|
||||||
take_aux : Nat -> List a -> List a -> List a
|
take_aux : Nat -> List a -> List a -> List a
|
||||||
take_aux Z xs acc = reverseOnto [] acc
|
take_aux Z xs acc = reverseOnto [] acc
|
||||||
@ -77,16 +66,11 @@ export
|
|||||||
take_ext :
|
take_ext :
|
||||||
(n : Nat) -> (xs : List a) ->
|
(n : Nat) -> (xs : List a) ->
|
||||||
Data.List.take n xs = Data.List.TailRec.take n xs
|
Data.List.take n xs = Data.List.TailRec.take n xs
|
||||||
take_ext n xs = Calculate [
|
take_ext n xs = Calc $
|
||||||
Data.List.take n xs
|
|~ Data.List.take n xs
|
||||||
==| Refl ,
|
~~ reverse [] ++ (Data.List.take n xs) ...( Refl )
|
||||||
reverse [] ++ (Data.List.take n xs)
|
~~ reverseOnto (Data.List.take n xs) [] ...( sym (revOnto (Data.List.take n xs) []) )
|
||||||
==| sym (revOnto (Data.List.take n xs) []) ,
|
~~ take_aux n xs [] ...( sym (lemma n xs []) )
|
||||||
reverseOnto (Data.List.take n xs) []
|
|
||||||
==| sym (lemma n xs []) ,
|
|
||||||
take_aux n xs []
|
|
||||||
==| QED
|
|
||||||
]
|
|
||||||
where
|
where
|
||||||
lemma : (n : Nat) -> (xs, acc : List a) ->
|
lemma : (n : Nat) -> (xs, acc : List a) ->
|
||||||
take_aux n xs acc = reverseOnto (Data.List.take n xs) acc
|
take_aux n xs acc = reverseOnto (Data.List.take n xs) acc
|
||||||
@ -249,12 +233,10 @@ mergeReplicate_ext : (sep : a) -> (xs : List a) -> (acc : List a) ->
|
|||||||
mergeReplicate_aux sep xs acc =
|
mergeReplicate_aux sep xs acc =
|
||||||
reverseOnto (mergeReplicate sep xs) acc
|
reverseOnto (mergeReplicate sep xs) acc
|
||||||
mergeReplicate_ext sep [] acc = Refl
|
mergeReplicate_ext sep [] acc = Refl
|
||||||
mergeReplicate_ext sep (x::xs) acc = Calculate [
|
mergeReplicate_ext sep (x::xs) acc = Calc $
|
||||||
mergeReplicate_aux sep xs (x :: sep :: acc)
|
|~ mergeReplicate_aux sep xs (x :: sep :: acc)
|
||||||
==| mergeReplicate_ext sep xs (x :: sep :: acc) ,
|
~~ reverseOnto (sep :: x :: mergeReplicate sep xs) acc
|
||||||
reverseOnto (sep :: x :: mergeReplicate sep xs) acc
|
...( mergeReplicate_ext sep xs (x :: sep :: acc) )
|
||||||
==| QED
|
|
||||||
]
|
|
||||||
|
|
||||||
export
|
export
|
||||||
intersperse : a -> List a -> List a
|
intersperse : a -> List a -> List a
|
||||||
@ -314,9 +296,10 @@ mergeByOnto : List a -> (a -> a -> Ordering) -> List a -> List a -> List a
|
|||||||
mergeByOnto acc order [] right = reverseOnto right acc
|
mergeByOnto acc order [] right = reverseOnto right acc
|
||||||
mergeByOnto acc order left [] = reverseOnto left acc
|
mergeByOnto acc order left [] = reverseOnto left acc
|
||||||
mergeByOnto acc order left@(x::xs) right@(y::ys) =
|
mergeByOnto acc order left@(x::xs) right@(y::ys) =
|
||||||
case order x y of
|
-- We need the variant annotations (bug #300)
|
||||||
LT => mergeByOnto (x :: acc) order xs right
|
case order x y of
|
||||||
_ => mergeByOnto (y :: acc) order left ys
|
LT => mergeByOnto (x :: acc) order (assert_smaller left xs) right
|
||||||
|
_ => mergeByOnto (y :: acc) order left (assert_smaller right ys)
|
||||||
|
|
||||||
mergeByOnto_ext : (acc : List a)
|
mergeByOnto_ext : (acc : List a)
|
||||||
-> (order : a -> a -> Ordering)
|
-> (order : a -> a -> Ordering)
|
||||||
@ -324,7 +307,9 @@ mergeByOnto_ext : (acc : List a)
|
|||||||
-> reverseOnto (mergeBy order left right) acc
|
-> reverseOnto (mergeBy order left right) acc
|
||||||
= mergeByOnto acc order left right
|
= mergeByOnto acc order left right
|
||||||
mergeByOnto_ext acc order [] right = Refl
|
mergeByOnto_ext acc order [] right = Refl
|
||||||
mergeByOnto_ext acc order left [] = ?bug139
|
mergeByOnto_ext acc order left [] with( left)
|
||||||
|
mergeByOnto_ext acc order _ [] | [] = Refl
|
||||||
|
mergeByOnto_ext acc order _ [] | (_::_) = Refl
|
||||||
mergeByOnto_ext acc order left@(x::xs) right@(y::ys) with (order x y)
|
mergeByOnto_ext acc order left@(x::xs) right@(y::ys) with (order x y)
|
||||||
mergeByOnto_ext acc order left@(x::xs) right@(y::ys) | LT =
|
mergeByOnto_ext acc order left@(x::xs) right@(y::ys) | LT =
|
||||||
mergeByOnto_ext (x :: acc) order xs (y::ys)
|
mergeByOnto_ext (x :: acc) order xs (y::ys)
|
||||||
@ -368,27 +353,31 @@ export
|
|||||||
sortBy : (cmp : a -> a -> Ordering) -> (xs : List a) -> List a
|
sortBy : (cmp : a -> a -> Ordering) -> (xs : List a) -> List a
|
||||||
sortBy cmp [] = []
|
sortBy cmp [] = []
|
||||||
sortBy cmp [x] = [x]
|
sortBy cmp [x] = [x]
|
||||||
sortBy cmp xs = let (x, y) = sortBy_split xs in
|
sortBy cmp zs = let (xs, ys) = sortBy_split zs in
|
||||||
Data.List.TailRec.mergeBy cmp
|
Data.List.TailRec.mergeBy cmp
|
||||||
(Data.List.TailRec.sortBy cmp (assert_smaller xs x))
|
(Data.List.TailRec.sortBy cmp (assert_smaller zs xs))
|
||||||
(Data.List.TailRec.sortBy cmp (assert_smaller xs y))
|
(Data.List.TailRec.sortBy cmp (assert_smaller zs ys))
|
||||||
|
|
||||||
|
|
||||||
{-- -- This code seems to make Idris2 loop
|
{- Can't really finish this proof because Data.List doesn't export the definition of sortBy. -}
|
||||||
|
{-
|
||||||
export
|
export
|
||||||
sortBy_ext : (cmp : a -> a -> Ordering) -> (xs : List a) ->
|
sortBy_ext : (cmp : a -> a -> Ordering) -> (xs : List a) ->
|
||||||
Data.List.sortBy cmp xs = Data.List.TailRec.sortBy cmp xs
|
Data.List.sortBy cmp xs = Data.List.TailRec.sortBy cmp xs
|
||||||
sortBy_ext cmp [] = Refl
|
sortBy_ext cmp [] = Refl
|
||||||
sortBy_ext cmp [x] = Refl
|
sortBy_ext cmp [x] = Refl
|
||||||
sortBy_ext cmp xs@(y::ys) = let (x, y) = split xs in
|
sortBy_ext cmp zs'@(z::zs) =
|
||||||
Calculate [
|
Calc $
|
||||||
Data.List.mergeBy cmp
|
|~ Data.List.sortBy cmp (z::zs)
|
||||||
(Data.List.sortBy cmp (assert_smaller xs x))
|
~~ (let (xs, ys) = sortBy_split zs' in
|
||||||
(Data.List.sortBy cmp (assert_smaller xs y))
|
Data.List.mergeBy cmp
|
||||||
==| ?help1 ,
|
(Data.List.sortBy cmp xs)
|
||||||
|
(Data.List.sortBy cmp ys))
|
||||||
|
...( ?help0 )
|
||||||
|
~~
|
||||||
|
let (xs, ys) = sortBy_split (z::zs) in
|
||||||
Data.List.TailRec.mergeBy cmp
|
Data.List.TailRec.mergeBy cmp
|
||||||
(Data.List.TailRec.sortBy cmp (assert_smaller xs x))
|
(Data.List.TailRec.sortBy cmp xs)
|
||||||
(Data.List.TailRec.sortBy cmp (assert_smaller xs y))
|
(Data.List.TailRec.sortBy cmp ys)
|
||||||
==| QED
|
...( ?help1 )
|
||||||
]
|
-}
|
||||||
--}
|
|
||||||
|
@ -1,42 +1,37 @@
|
|||||||
||| Until Idris2 starts supporting the 'syntax' keyword, here's a
|
||| Until Idris2 starts supporting the 'syntax' keyword, here's a
|
||||||
||| poor-man's equational reasoning
|
||| poor-man's equational reasoning
|
||||||
module Syntax.PreorderReasoning
|
module Syntax.PreorderReasoning
|
||||||
|
|
||||||
||| Deep embedding of equation derivation sequences.
|
infixl 0 ~~
|
||||||
||| Using the Nil, (::) constructors lets us use list syntax.
|
prefix 1 |~
|
||||||
|
infix 1 ...
|
||||||
|
|
||||||
|
|||Slightly nicer syntax for justifying equations:
|
||||||
|
|||```
|
||||||
|
||| |~ a
|
||||||
|
||| ~~ b ...( justification )
|
||||||
|
|||```
|
||||||
|
|||and we can think of the `...( justification )` as ASCII art for a thought bubble.
|
||||||
public export
|
public export
|
||||||
data Derivation : (x : a) -> (y : b) -> Type where
|
(...) : (x : a) -> (y ~=~ x) -> (z : a ** y ~=~ z)
|
||||||
Nil : Derivation x x
|
(...) x pf = (x ** pf)
|
||||||
(::) : (x = y) -> Derivation y z -> Derivation x z
|
|
||||||
|
public export
|
||||||
|
data FastDerivation : (x : a) -> (y : b) -> Type where
|
||||||
|
(|~) : (x : a) -> FastDerivation x x
|
||||||
|
(~~) : FastDerivation x y -> (step : (z : c ** y ~=~ z)) -> FastDerivation x z
|
||||||
|
|
||||||
infix 1 ==|
|
public export
|
||||||
|
Calc : {x : a} -> {y : b} -> FastDerivation x y -> x ~=~ y
|
||||||
|
Calc (|~ x) = Refl
|
||||||
|
Calc {y} ((~~) {z=y} {y=y} der (y ** Refl)) = Calc der
|
||||||
|
|
||||||
||| Explicate the term under consideration and the justification for
|
{- -- requires import Data.Nat
|
||||||
||| the next step.
|
0
|
||||||
export
|
|
||||||
(==|) : (x : a) -> (x = y) -> x = y
|
|
||||||
(==|) x pf = pf
|
|
||||||
|
|
||||||
||| Finishg the derivation.
|
|
||||||
||| A bit klunky, but this /is/ a poor-man's version.
|
|
||||||
export
|
|
||||||
QED : {x : a} -> x = x
|
|
||||||
QED = Refl
|
|
||||||
|
|
||||||
export
|
|
||||||
Calculate : Derivation x y -> x = y
|
|
||||||
Calculate [] = Refl
|
|
||||||
Calculate (Refl :: der) = Calculate der
|
|
||||||
|
|
||||||
{--
|
|
||||||
||| Requires Data.Nata
|
|
||||||
example : (x : Nat) -> (x + 1) + 0 = 1 + x
|
example : (x : Nat) -> (x + 1) + 0 = 1 + x
|
||||||
example x = Calculate [
|
example x =
|
||||||
(x + 1) + 0
|
Calc $
|
||||||
==| plusZeroRightNeutral (x + 1) ,
|
|~ (x + 1) + 0
|
||||||
x + 1
|
~~ x+1 ...( plusZeroRightNeutral $ x + 1 )
|
||||||
==| plusCommutative x 1 ,
|
~~ 1+x ...( plusCommutative x 1 )
|
||||||
1 + x
|
-}
|
||||||
==| QED
|
|
||||||
]
|
|
||||||
--}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user