Defining a function that returns one element satisfying the condition

Question

I want to declare a function that yeilds the element (b, n) that the b is equal to true.

Require Export List.
Import Coq.Lists.List.ListNotations.

Definition lstest := list (bool * nat).

Fixpoint existbool (l : lstest) : option (bool * nat) :=
match l with
| [] => None
| (b, n) :: l' => if b then Some (b, n) else existbool l'
end.

The function always get the first element satisfyting b = true. I want to express that there exists an element satisfyting b = true and returns the element. How can I define such a function?

Answer

You could write a function get_number that requires a proof that the list has a true value somewhere.

Definition has_true (l : lstest) := exists n, In (true, n) l.

get_number is defined with the help of refine which lets us leave 'holes' (written _) in the proof term to fill in later. Here we have two holes; one for the absurd case when the list is [], and one where we construct the proof term for the recursive call.

get_number: forall l : lstest, has_true l -> nat
l: lstest
H: has_true l

nat
get_number: forall l : lstest, has_true l -> nat
l: lstest
H: has_true l
L: l = []

nat
get_number: forall l : lstest, has_true l -> nat
l: lstest
H: has_true l
p: (bool * nat)%type
l': list (bool * nat)
b: bool
n: nat
L: l = (false, n) :: l'
has_true l'
get_number: forall l : lstest, has_true l -> nat
l: lstest
H: has_true l
L: l = []

nat
get_number: forall l : lstest, has_true l -> nat
l: lstest
H: has_true l
L: l = []

False
get_number: forall l : lstest, has_true l -> nat
H: has_true []

False
now inversion H.
get_number: forall l : lstest, has_true l -> nat
l: lstest
H: has_true l
p: (bool * nat)%type
l': list (bool * nat)
b: bool
n: nat
L: l = (false, n) :: l'

has_true l'
get_number: forall l : lstest, has_true l -> nat
l': list (bool * nat)
n: nat
H: has_true ((false, n) :: l')
p: (bool * nat)%type
b: bool

has_true l'
get_number: forall l : lstest, has_true l -> nat
l': list (bool * nat)
n: nat
H: has_true ((false, n) :: l')
p: (bool * nat)%type
b: bool
x: nat
H0: In (true, x) ((false, n) :: l')

has_true l'
inversion H0; [inversion H1 | now (exists x)]. Defined.

The function uses the convoy pattern so that the match statement does not forget the shape of l in the different branches.

If you want to, you can prove rewriting lemmas to make it easier to use.

l: list (bool * nat)
m: nat
H: has_true ((false, m) :: l)

exists H' : has_true l, get_number ((false, m) :: l) H = get_number l H'
l: list (bool * nat)
m: nat
H: has_true ((false, m) :: l)

exists H' : has_true l, get_number ((false, m) :: l) H = get_number l H'
eexists; reflexivity. Qed.
l: list (bool * nat)
m: nat
H: has_true ((true, m) :: l)

get_number ((true, m) :: l) H = m
l: list (bool * nat)
m: nat
H: has_true ((true, m) :: l)

get_number ((true, m) :: l) H = m
reflexivity. Qed.
H: has_true []
m: nat

get_number [] H <> m
H: has_true []
m: nat

get_number [] H <> m
now inversion H. Qed.
l: lstest
H1, H2: has_true l

get_number l H1 = get_number l H2
l: lstest
H1, H2: has_true l

get_number l H1 = get_number l H2
induction l as [ | [[|] ?] l']; eauto; now inversion H1. Qed.