fac n = if n < 2 then 1 else n * fac (n-1)
main = do
putStrLn "Enter a number: "
number <- getLine
print $ number >>= fac
I do not know how to write a recursive factorial function without if statements. Our professor said somethings about lambda calculus.
Pattern matching and guards are two particularly straightforward ways. Guards are essentially another syntax for if-then-else; they look like this:
fac n | n < 2 = 1
| otherwise = n * fac (n-1)
Unlike if-then-else, they cleanly support multiple conditions; one could also write, for example,
fac n | n < 0 = error "nah"
| n == 0 = 1
| n == 1 = 1
| n > 1 = n * fac (n-1)
which would look much less pretty in if-then-else form.
With pattern matching, one would typically write multiple defining equations:
fac 0 = 1
fac 1 = 1
fac n = n * fac (n-1)
For numbers in particular, this also desugars to essentially an if-then-else; but for data types with less compiler integration often cannot be emulated with if-then-else, and also often leads to very natural-looking code.
Another very nice approach would be to push your recursion into existing Prelude functions; the more you can spot iteration patterns in practice the more bugs you can avoid by not re-implementing the same loops over and over. For this one, you might use product
and the special enumeration syntax:
fac n = product [1..n]
A more advanced (and significantly worse) technique would be to define a new kind of number; e.g. Church numerals allow the producer of the number to drive the recursion, and the consumer (here, fac
) to just supply base cases. In this style, you might see something like this:
fac n = fst (n (1,1) (\(prod, sum) -> (prod*sum, sum+1)))
(But note well that this requires a very special kind of number -- certainly the type of fac
is not one of a function that could accept Int
or Integer
!) This joke is taken to its logical and horrifying conclusion in The Evolution of a Haskell Programmer.