Equational reasoning is fun! You'll get the knack of it pretty quickly, if you do a few proofs yourself. I warmly recommend ch. 13 of Graham Hutton's Programming in Haskell for a concise introduction.
Anyway, you can prove that, for all equatable and finite (see Tom Ellis's answer) xs
, ys
and z
,
elem z (xs ++ ys) == elem z xs || elem z ys
by induction on list xs
. For that, you need to use the definitions of ++
, ||
, and elem
, and use the fact that ||
is associative:
[] ++ ys = ys
(x:xs) ++ ys = x : (xs ++ ys)
False || b = b
True || _ = True
elem _ [] = False
elem x (y:ys) = x == y || elem x ys
Base case
Let ys
be a value of type Eq a => [a]
, and z
a value of type Eq a => a
; then we have
elem z ([] ++ ys)
= {applying ++}
elem z ys
= {unapplying ||}
False || elem z ys
= {unapplying elem}
elem z [] || elem z ys
Inductive case
Let xs
, ys
be values of type Eq a => [a]
, and x
, z
values of type Eq a => a
. Assume (induction hypothesis) that
elem z (xs ++ ys) == elem z xs || elem z ys
Then we have
elem z ((x:xs) ++ ys)
= {applying ++)
elem z (x : (xs ++ ys))
= {applying elem}
z == x || elem (xs ++ ys)
= {induction hypothesis}
z == x || (elem z xs || elem z ys)
= {associativity of ||}
(z == x || elem z xs) || elem z ys
= {unapplying elem}
elem z (x:xs) || elem z ys
(QED)