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
.
Yes, the return types are inferred. Although in most real cases you would declare a function
def
's return type, because it's safer to be explicit about types that are part of a public API.