Corner cases of mathematical definitions tend to take people by surprise, such as that 0 factorial equals 1 and that universal quantification over the empty set is always true. In these examples, functional programming (but never procedural programming) is illuminating. In Scala:
def factorial(n: Int): Int =
(1 to n).fold(1)(_*_)
def all[A](set: Set[A], p: A => Boolean): Boolean =
set.map(p).fold(true)(_&&_)
It's impossible to write these folds without working out the value of the corner cases, and each shows up explicitly in the code as the first argument to a fold: 1
and true
.
I don't know Scala well, so must ask: In these examples is type-inference in play, such that the types of the results go unstated?