Here's a reasonable definition from the Haskell wiki:
A total function is a function that is defined for all possible values of its input. That is, it terminates and returns a value.
A partial function is a function that is not defined for all possible input values; in some cases instead of returning a value, it may never return at all (think infinite cycles), throw an exception (which usually states "this is undefined for this input value" or "unexpected input" or whatever) or simply crash the system.
A well-known example of a partial function is the integer division, a divided by b
: it's not defined when b
is zero!
Another example is head
, the Haskell function that takes the first element of a list, which throws an error if the list is empty! Something like this:
head :: [a] -> a // this is the signature
head (first : rest) = first
head _ = ... // This is an error! What is the first element of the empty list?
Partial functions like head
unfortunately exist in Haskell for historical reasons. Note it can be made total like this:
headMaybe :: [a] -> Maybe a
headMaybe (first : rest) = Just first
headMaybe _ = Nothing
Then you can safely call head []
([]
is the empty list) and it will return Nothing
instead of throwing.
Note that when looking at the original head
, I cannot know just by looking at its definition that it may throw an error in some cases; I need to look at its implementation instead! That's bad. Compare this with headOption
: just by looking at its type I know it sometimes returns a Just x
and sometimes a Nothing
, and I don't have to examine the implementation.