4

We're urged to avoid partial functions with seemingly more emphasis in Haskell than other languages.

Is this because partial functions are a more frequent risk in Haskell than other languages (c.f. this question), or is it that avoiding them in other languages is impractical to the point of little consideration?

kostmo
  • 6,222
  • 4
  • 40
  • 51
  • 6
    Related: I believe that `-Wincomplete-patterns` should be turned on by default in GHC. Actually, I have the stronger opinion that incomplete patterns should be an error, so that if partiality is actually wanted the programmer has to be explicit about it and write `_ -> undefined` or something similar. – chi Jul 14 '17 at 11:19

2 Answers2

8

Is this because partial functions are a more frequent risk in Haskell than other languages (c.f. this question), or is it that avoiding them in other languages is impractical to the point of little consideration?

Certainly the latter. The most commonly used languages all have some notion of the null value as an inhabitant of every type, the practical effect being that every value is akin to haskell's Maybe a.

You can argue that in haskell we have the same issue: bottoms can hide anywhere, e.g.

uhoh :: String
uhoh = error "oops"

But this isn't really the case. In haskell all bottom are morally equivalent and we can reason about code as if they didn't exist. If we could catch exceptions in pure code, this would no longer be the case. Here's an interesting discussion.

And just a subjective addendum, I think intermediate haskell developers tend to be aware of whether a function is partial, and to complain loudly when they are surprised to find they were wrong. At the same time a fair portion of the Prelude contains partial functions, such as tail and / and these haven't changed in spite of much attention and many alternative preludes, which I think is evidence that the language and standard lib probably struck a pretty decent balance.

EDIT I agree that Alexey Romanov's answer is an important part of the picture as well.

jberryman
  • 16,334
  • 5
  • 42
  • 83
  • Aside from the absence of `null` in Haskell, are there any other language features that make partial functions easier to avoid? I'm thinking about sum types or pattern matching, but have not yet articulated a reason. – kostmo Jul 14 '17 at 07:33
  • 4
    @kostmo Mostly `-Wall` helps you to avoid such errors. With ADT's and pattern matching compiler can tell you whether you covered all cases or not. – Shersh Jul 14 '17 at 10:38
8

One reason why partial functions are significantly worse in Haskell compared to other languages is the lack of stack traces by default. When you call e.g. head on an empty list, you only get Prelude.head: empty list. Good luck figuring out which call of head is the problem or where the empty list came from! Of course, it may not even be in your code, but in some library you are using.

To get a stack trace, you need to either compile with profiling enabled or to make it available explicitly: see https://hackage.haskell.org/package/base-4.9.1.0/docs/GHC-Stack.html and https://wiki.haskell.org/Debugging. And both of these options appeared in relatively recent GHC versions (and work on improving them is ongoing).

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • Also, since catching an exception tells you something about the state of execution, you can only really do that in the 'IO' monad. That limits the usefulness of a lot of exception handling in other languages. – Alec Jul 14 '17 at 09:44