The boolean operators &&
and ||
take boolean values as their operands.
Sometimes you want to apply a boolean operator to a list of boolean values.
Writing something like a && b && c && d && e
can quickly become unwieldy and
tedious. What you want are versions of &&
and ||
that can operate on lists,
not necessarily of boolean values. Well, this is your lucky day. For a limited
time only starting from now to eternity, you can use various functional versions
of your favourite boolean operators. Too good to be True
? Au contraire, mon
ami(e).
The function and
outputs True
if all elements of a list are True
,
and False
otherwise. It is the function counterpart of the operator &&
. The
function and
is useful when we want to know whether all elements of a list
satisfy a given property. For example, below we check whether all elements of a
list are even.
1
2
3
4
5
6
ghci> and [even x | x <- [1 .. 10]]
False
ghci> and [even x | x <- [2, 4 .. 10]]
True
ghci> and [even x | x <- [1, 3 .. 10]]
False
Pietro manages a pet shop. As part of his monthly routine, Pietro checks to see whether all pets in his shop have had a health check within the last 12 months. A number of new pets were delivered to the shop recently. Pietro does not recall bringing the new pets to a veterinary clinic within the last two weeks. The following shows the pets database and the health check status of all animals in Pietro’s shop.
:include: file=”assets/src/list/pet.hs”, line=25:92
The function or
outputs True
if one element of a list is True
. Like
its operator counterpart ||
, or
outputs False
if all elements are False
.
The function or
is useful in situations where we only care that one element is
True
. It might be the case that multiple elements are True
. However, we are
only interested in whether at least one element is True
.
For example, the list of integers from 1 up to and including 10 has at least one
odd number. Similarly, the list [1 .. 10]
has at least one even number. The
following GHCi session should confirm the above observations:
1
2
3
4
ghci> or [even x | x <- [1 .. 10]]
True
ghci> or [odd x | x <- [1 .. 10]]
True
The vowels of the English alphabet are “A”, “E”, “I”, “O”, and “U”. Some words in English do not contain a vowel at all. Here are some common, and not so common, words that consist of only consonants:
C | G | P | S | T | W |
---|---|---|---|---|---|
cry | glyph | ply | sty | thy | why |
crypt | gym | pwn | sync | try | wry |
cyst | gypsy | pygmy | syzygy | tryst | wyrm |
If you were to test each of the above words for vowels, the result would be
False
. Observe:
:include: file=”assets/src/list/word.hs”, line=25:60
The function all
is a predicate counterpart of and
. Whereas
and
expects all elements of a list to be boolean values, all
accepts a
predicate that is used to determine whether all elements of a list satisfy the
predicate. For example, suppose we have a list of integers. We do not know
whether all the integers are positive. The function all
can help us in this
scenario. Consider the GHCi session below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ghci> import Control.Monad
ghci> import System.Random.Stateful
ghci> ella <- replicateM 20 (uniformRM (-3, 20) globalStdGen :: IO Integer)
ghci> ellb <- replicateM 20 (uniformRM (-3, 20) globalStdGen :: IO Integer)
ghci> ellc <- replicateM 20 (uniformRM (1, 20) globalStdGen :: IO Integer)
ghci> ella
[1,2,15,12,1,10,17,-3,7,20,-3,3,8,8,14,19,11,-2,1,18]
ghci> all (\x -> x > 0) ella
False
ghci> ellb
[1,10,4,1,3,2,10,-1,6,4,20,0,4,-2,14,19,-3,18,16,13]
ghci> all (\x -> x > 0) ellb
False
ghci> ellc
[6,9,9,13,16,2,17,11,15,7,2,7,9,16,20,8,4,7,18,5]
ghci> all (\x -> x > 0) ellc
True
As another example, consider the table below of the goals scored by players of Arsenal during the 2022—2023 season of the Premier League. We included only male players who scored at least one goal. The header “Goals-PK” means non-penalty goals.
Player | Goals | Goals-PK |
---|---|---|
Ben White | 2 | 2 |
Bukayo Saka | 14 | 12 |
Eddie Nketiah | 4 | 4 |
Fabio Vieira | 1 | 1 |
Gabriel Dos Santos | 3 | 3 |
Gabriel Jesus | 11 | 10 |
Gabriel Martinelli | 15 | 15 |
Granit Xhaka | 7 | 7 |
Jakub Kiwior | 1 | 1 |
Leandro Trossard | 1 | 1 |
Martin Ødegaard | 15 | 15 |
Oleksandr Zinchenko | 1 | 1 |
Rob Holding | 1 | 1 |
Reiss Nelson | 3 | 3 |
Thomas Partey | 3 | 3 |
William Saliba | 2 | 2 |
Our question is: Were all the goals scored non-penalty? If a player scored $g$ goals and statistics says the player scored $h$ non-penalty goals, then all goals scored by the player is non-penalty provided that $g = h$. I’m too lazy to check by hand. Let’s delegate the manual work to Haskell:
:include: file=”assets/src/list/arsenal.hs”, line=25:60
The function any
is the predicate counterpart of or
. The
function or
requires all elements of a list to be boolean values. On the other
hand, any
requires a predicate based upon which the function decides whether
some elements of a list satisfy the predicate.
Consider a bunch of random integers. We know that there are negative integers and zero. Is there at least one positive integer? Let’s find out.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ghci> import Control.Monad
ghci> import System.Random.Stateful
ghci> a <- replicateM 20 (uniformRM (-20, 3) globalStdGen :: IO Integer)
ghci> b <- replicateM 20 (uniformRM (-20, 2) globalStdGen :: IO Integer)
ghci> c <- replicateM 20 (uniformRM (-20, 0) globalStdGen :: IO Integer)
ghci> a
[-16,-14,-1,-16,-19,-4,-8,-19,-1,-5,-6,1,-7,-3,-8,-15,-4,-11,-17,-10]
ghci> any (\x -> x > 0) a
True
ghci> b
[2,-4,-5,-5,2,0,2,-1,-18,-14,-2,-15,-11,-20,-15,-11,0,-4,-14,-4]
ghci> any (\x -> x > 0) b
True
ghci> c
[-20,-17,-10,-1,-6,-6,-3,-4,-3,-3,-1,-8,-4,-7,-19,-14,0,-15,-1,-7]
ghci> any (\x -> x > 0) c
False
Violet wants to increase her vocabulary. The words in her list vary in length. She wants to know whether the list has a short word, i.e. a word of at most 5 letters. Learning short words all the time is no fun. Violet also wants to determine whether the list has a long word, i.e. a word of at least 8 letters. Let’s use Haskell to find out:
1
2
3
4
5
ghci> a = ["benign", "elixir", "tumid", "intemperance", "narcissist"]
ghci> any (\str -> length str <= 5) a
True
ghci> any (\str -> length str >= 8) a
True
:exercise:
Consider the script
:script: file=”assets/src/list/arsenal.hs”
from the section all. Modify the script to use any
to determine
whether any of the goals scored were a result of a penalty kick.
:exercise: Recall the script :script: file=”assets/src/list/pet.hs” from the section and. Modify the script to determine whether all birds have had a health check within the last 12 months. Furthermore, determine whether some of the birds have had a health check within the same time period.
:exercise: Many words in English that do not have a vowel use the letter “Y” to simulate a vowel sound. Refer to the script :script: file=”assets/src/list/word.hs” from the section or. Modify the script to determine whether some of the words in the word list do not use “Y”. Print such words to standard output.
:exercise:
Recall the exercise on
Gilbreath’s conjecture from the section
Free range numbers. Let $\ell$ be a list of prime numbers not
exceeding an integer $n > 1$. Successive application of the difference operation
would eventually result in the list [1]
. Determine how many times you must
perform the difference operation in order to obtain a list that satisfies one of
the properties below:
The values of $n$ are drawn from the list [10, 100, 1000, 10000, 100000]
.
:exercise: The Britannica Dictionary has a list of 100 core words for the TOEFL. Let’s refer to these words as the Britannica core. Use the Britannica core to answer the following questions.
:exercise: Consider the list below of female players of Sydney FC during the 2022—2023 soccer season in Australia.
:include: file=”assets/src/list/solution/sydney.hs”, line=28:69
Write a program to help you answer the following questions:
:exercise:
Implement the function and
without using the operator &&
.
:exercise:
Implement the function or
without using the operator ||
.
:exercise:
Implement the function all
without using the operator &&
.
:exercise:
Implement the function any
without using the operator ||
.