2

AFAIK in Haskell it is heavily recommended to avoid partial functions; and if these seem unavoidable (eg head) then return a Maybe. At least, so the Haskell wiki says 1 2

What's the use of the pattern?

Assume I have a function that seems partial. It wants its arguments to fulfil some requirements that seem difficult to check compile time. Also, unless I screwed up on other parts of my code, the function should never be called with non-conformant arguments because it does not make sense to call it with such arguments.

If I write a partial function and I have a bug then my program crashes. This is bad so instead...

If I follow the advice and return a Maybe - I'll have to finally pattern-match this Maybe sooner or later! If finally main :: IO() receives a Maybe when it wants to print out some sensible data, what is main going to do?

Print out an error that says that the programmer is an idiot?

Ugh... we're precisely at what would happen if I kept the function partial. Except that I don't get an information where I screwed up that easily.

What am I missing here?

2

Partial functions are bad because there are now illegal states in your software. The most elegant solution to avoid these is to make illegal states unrepresentable, for example by introducing a new type for a value that guarantees certain properties.

However, Haskell's type system is too weak to represent certain properties like “a list that contains at least one element”. This makes workarounds necessary.

  • If your software enters an illegal state, then immediately crashing is a sensible thing to do. Something happened that you didn't expect, so you don't really have any idea for how to recover from that illegal state.

  • By taking a partial function a -> b and turning it into a function a -> Maybe b you can write it as a total function – those inputs that you don't want to process are not illegal, they just map to Nothing. The type system is happy, you are happy. Yes, that monad will now propagate through the rest of your program, but Haskell provides the necessary abstractions to make this bearable. In some cases it might make sense to return a default value instead.

The best approach probably depends on your view on this function – is this actually a partial function that just ignores some inputs? Or are there illegal states in your program that need to be ruled out, possibly by runtime checks?

Haskell's head :: [a] -> a function is an example where they decided that passing an empty list is illegal, so that a runtime error will be thrown. That is a pragmatic approach, but still valid. But whether that was the right design is very very debatable. In most of your code, it would likely be better to return a Maybe value, thus leaving the decision (error, propagate, default) to the caller.

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.