Section RLift.
Require Import List.
Definition lift {
A B:
Type} (
f:
A->
B) : (
option A ->
option B)
:=
fun a =>
match a with
|
None =>
None
|
Some a' =>
Some (
f a')
end.
Definition olift {
A B} (
f:
A ->
option B) (
x:
option A) :
option B :=
match x with
|
None =>
None
|
Some x' =>
f x'
end.
Definition bind {
A B:
Type}
a b := (@
olift A B b a).
Definition olift_some {
A B} (
f:
A ->
option B) (
x:
A) :
olift f (
Some x) =
f x.
Proof.
reflexivity. Qed.
Definition olift2 {
A B C} (
f:
A ->
B ->
option C) (
x1:
option A) (
x2:
option B) :
option C :=
match x1,
x2 with
|
Some d1,
Some d2 =>
f d1 d2
|
_,
_ =>
None
end.
Lemma olift2_none_r {
A B C} (
f:
A ->
B ->
option C) (
x1:
option A) :
olift2 f x1 None =
None.
Proof.
destruct x1; reflexivity.
Qed.
Lemma olift2_somes {
A B C} (
f:
A ->
B ->
option C) (
x1:
A) (
x2:
B) :
olift2 f (
Some x1) (
Some x2) =
f x1 x2.
Proof.
reflexivity. Qed.
Lemma lift_some_simpl {
A B:
Type} (
f:
A->
B)
x :
lift f (
Some x) =
Some (
f x).
Proof.
reflexivity.
Qed.
Lemma lift_some_simpl_eq {
A B:
Type} (
f:
A->
B)
x y :
f x =
f y <->
lift f (
Some x) =
Some (
f y).
Proof.
simpl; split; [|inversion 1]; congruence.
Qed.
Lemma lift_none_simpl {
A B:
Type} (
f:
A->
B) :
lift f None =
None.
Proof.
reflexivity. Qed.
Lemma lift_none {
A B:
Type} {
f:
A->
B} {
x} :
x =
None ->
lift f x =
None.
Proof.
intros; subst; reflexivity.
Qed.
Lemma lift_some {
A B:
Type} {
f:
A->
B} {
x y}
z :
x =
Some z ->
f z =
y ->
lift f x =
Some y.
Proof.
intros; subst; reflexivity.
Qed.
Lemma none_lift {
A B:
Type} {
f:
A->
B} {
x} :
lift f x =
None ->
x =
None.
Proof.
destruct x; simpl; intuition discriminate.
Qed.
Lemma some_lift {
A B:
Type} {
f:
A->
B} {
x y} :
lift f x =
Some y ->
{
z |
x =
Some z &
y =
f z}.
Proof.
destruct x; simpl; intuition; [inversion H; eauto|discriminate].
Qed.
Lemma lift_injective {
A B:
Type} (
f:
A->
B) :
(
forall x y,
f x =
f y ->
x =
y) ->
(
forall x y,
lift f x =
lift f y ->
x =
y).
Proof.
destruct x; destruct y; simpl; inversion 1; auto.
f_equal; auto.
Qed.
Fixpoint lift_map {
A B:
Type} (
f:
A ->
option B) (
l:
list A) :
option (
list B) :=
match l with
|
nil =>
Some nil
|
x::
l' =>
match (
f x)
with
|
None =>
None
|
Some x' =>
match lift_map f l'
with
|
None =>
None
|
Some l'' =>
Some (
x'::
l'')
end
end
end.
Fixpoint lift_filter {
A:
Type} (
f:
A ->
option bool) (
l:
list A) :
option (
list A) :=
match l with
|
nil =>
Some nil
|
x::
l' =>
match (
f x)
with
|
None =>
None
|
Some b =>
match lift_filter f l'
with
|
None =>
None
|
Some l'' =>
if b then Some (
x::
l'')
else Some l''
end
end
end.
Definition lift_app {
A:
Type} (
l1 l2:
option (
list A)) :
option (
list A) :=
match l1,
l2 with
|
Some l1',
Some l2' =>
Some (
l1'++
l2')
|
_,
_ =>
None
end.
Definition lift2 {
A B C:
Type} (
f:
A ->
B ->
C) (
x:
option A) (
y:
option B) :
option C :=
match x,
y with
|
Some x',
Some y' =>
Some (
f x'
y')
|
_,
_ =>
None
end.
Lemma lift_filter_eq {
A} (
f g:
A ->
option bool)
l :
(
forall a,
In a l ->
f a =
g a) ->
lift_filter f l =
lift_filter g l.
Proof.
intros.
induction l;
try reflexivity.
simpl in *.
assert (
forall a0,
In a0 l ->
f a0 =
g a0).
intros;
apply H.
right;
assumption.
specialize (
IHl H0).
assert (
f a =
g a).
apply (
H a);
left;
reflexivity.
clear H.
rewrite H1.
rewrite IHl.
reflexivity.
Qed.
Lemma lift_app_filter {
A:
Type} (
p:
A ->
option bool) (
l1 l2:
list A):
lift_filter p (
app l1 l2) =
lift2 (@
app A) (
lift_filter p l1) (
lift_filter p l2).
Proof.
induction l1;
simpl.
destruct (
lift_filter p l2);
reflexivity.
destruct (
p a);
simpl;
try reflexivity.
rewrite IHl1;
clear IHl1.
destruct (
lift_filter p l1);
try reflexivity.
destruct b;
destruct (
lift_filter p l2);
reflexivity.
Qed.
Lemma lift_id {
A} (
x:
option A) :
lift (
fun l'' =>
l'')
x =
x.
Proof.
destruct x; reflexivity.
Qed.
Lemma match_lift_id {
A} (
x:
option A) :
match x with
|
None =>
None
|
Some l'' =>
Some l''
end =
x.
Proof.
destruct x; reflexivity.
Qed.
End RLift.
Hint Rewrite @
olift_some :
alg.
Hint Rewrite @
olift2_none_r :
alg.
Hint Rewrite @
olift2_somes :
alg.
Ltac case_option
:=
match goal with
[|-
context [
match ?
x with
|
Some _ =>
_
|
None =>
_
end]] =>
case_eq x
end.
Ltac case_lift
:=
match goal with
[|-
context [
lift _ ?
x]] =>
case_eq x
end.
Ltac case_option_in H
:=
match type of H with
context [
match ?
x with
|
Some _ =>
_
|
None =>
_
end] =>
let HH:=(
fresh "
eqs")
in case_eq x; [
intros ?
HH|
intros HH];
try rewrite HH in H
end.
Ltac case_lift_in H
:=
match type of H with
context [
lift _ ?
x] =>
let HH:=(
fresh "
eqs")
in case_eq x; [
intros ?
HH|
intros HH];
try rewrite HH in H
end.