7

I'm not finding via Google any explanation that my brain can grasp. Can someone explain this, and if possible, give an example of each using either pseudocode or C#?

The term 'total' function was introduced to me in the comments section of this question. The comment is:

when you work with total functions, you can compose them with other functions and use them in higher order functions without worrying about error results "not encoded in the type", i.e. exceptions. – Andres F.

I'm intrigued by this comment.

  • 2
    I think this is not a real dupe. This question is about concepts on functional programming (see tag). The referred question is about algorithmic terminology. The wording of the other question is very different and only remotely connected to this one. OP could not have recognized his interest therein. It appears that one answer explains what a total function is, and another refers to total and partial functions without elaborating further. But the fact of having some overlapping elements in the answer is not sufficient IMO for making it a dupe. – Christophe Oct 29 '16 at 22:37
  • This has a community close on it, meaning the question author closed it as a duplicate. Yet there are four reopen votes? Madness! – user22815 Nov 4 '16 at 19:21
  • @Snowman The question author is not the only one who gets to decide :) – Andres F. Nov 4 '16 at 19:50
18

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.

  • 1
    "Partial functions like head unfortunately exist in Haskell ": Why do you say "unfortunately"? What would be the alternative to head being partial? – Giorgio Oct 28 '16 at 21:49
  • 5
    @Giorgio The alternative would be something like the headMaybe function suggested near the end of the answer. Unlike head, where the user needs to assume/assert the list is not empty, headMaybe returns a Maybe type. When you want to extract the actual value from the maybe type, you need to explicitly state what should be done if it's Nothing. This means you can't use the value at the head of the list without specifying what to do if the list was empty. – Idan Arye Oct 28 '16 at 22:04
  • I think partial functions have their place as a form of assert. In Rust, for example, the Option type(similar to Haskell's Maybe) has the expect method, which means - give me the value, and if it's empty this means the code is buggy and you should crash the program with this error message. – Idan Arye Oct 28 '16 at 22:08
  • @IdanArye Haskell's Maybe has a similar partial function fromJust :: Maybe a -> a. I think they must be used with extreme care, if at all. The problem is that while you may know what you're doing at the exact place where you invoke this, it "taints" the enclosing function as well: now it too may throw an error. And so on and on. Now every caller must either trap the error (which cannot be done in pure code) or accept it has become partial itself. – Andres F. Oct 28 '16 at 22:15
  • That's why they should be treated as a form of assert. You don't ever want to catch and handle assertion errors - if an assertion error triggers it essentially means you have a bug in the code and the program's state is unstable. The only valid reasons to catch such errors is for logging/recording(write the error in a file, mail it to the developer, format it for HTTP response, display failure message in a test framework) or if you want to wrap it with a more meaningful error message. I see no merit in explicitly bubbling these errors up to main, where debuggers have no meaningful context. – Idan Arye Oct 28 '16 at 23:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.