We have previously seen the guard-sequence pattern which sits at the core of this implementation. The expression
"fizz" <$ guard (rem i 3 == 0)
will evaluate to Just "fizz"
whenever i
is divisible with three, and in all
other cases it evaluates to Nothing
. Thus, if a number is not divisible by any
of the three given, the list will evaluate to
[Nothing, Nothing, Nothing]
If a number is divisible by only five, but not three or seven, the list will be
[Nothing, Just "buzz", Nothing]
And if a number is divisible by, say, three and seven, but not five, the list will be
[Just "fizz", Nothing, Just "zork"]
These are smushed together by the mconcat
from the Monoid
interface, which
uses the generic smushing operation <>
. This behaves just as expected for our
strings-that-might-not-exist: it concatenates them together if they do exist,
otherwise it returns Nothing
.
Whatever we get out of mconcat
, we pass it to fromMaybe (show i)
which
replaces any Nothing
values with the string representation of the number
coming into the function, but passes through any actual values it receives
intact. This is the full fizzbuzz
function that converts a number to the
correct textual representation.
To make it an actual program, we loop through all numbers [1..100]
, convert
them with fizzbuzz
, and print the result.