This is easier to understand if we talk instead about all, any :: (a -> Bool) -> [a] -> Bool
. Intuitively:
all p
searches a list to find a counterexample to the predicate p
. It returns False
if and only if such a counterexample is found.
any p
searches a list to find an example that satisfies the predicate p
. It returns True
if and only if such an example is found.
Therefore:
all p []
is true because the empty list does not contain any counterexamples to p
.
any p []
is false because the empty list does not contain any examples that satisfy p
.
Note that:
and == all id
or == any id
So this reasoning extends to and, or :: [Bool] -> Bool
.
Note that mathematical logic often also works like this:
-- "All unicorns are Argentinian."
∀x. unicorn(x) → argentinian(x)
This proposition is true if unicorns don't exist. Logic newbies get confused by this as well...