I'm trying to figure out what is the best practice to write the Haskell equivalent of assert(0). I know that type safety dictates that an integer must be returned from scanList, however I wonder if there's a better way than what I wrote. Is there any way to avoid the arbitrary number 923 that is just stuck there?

I suggest using assertions only for invariants in your code (where a failure means a bug), they help document invariants and compliment your tests. assert calls have no overhead since they are removed when compiling with optimizations
– jberrymanFeb 11 at 14:50

2 Answers
2

If the first argument evaluates to True, then the result is the second argument. Otherwise an AssertionFailed exception is raised, containing a String with the source file and line number of the call to assert.

So instead of giving False as first argument you could actually check your if condition there:

The more idiomatic Haskell design would be to keep pure functions total. When using assert, you're throwing an exception, which makes the function partial. This means that you can no longer trust the type of the function. It claims to have the type [Either String Int] -> Int, but will fail with an exception at run-time under various conditions.

A total function would either stay within the Either monad, or could, alternatively, translate to Maybe:

You could simplify the code quite a bit, but I chose to keep it structurally as close to the OP as possible.

With a type like [Either String a] -> Maybe a, any caller knows that they have to handle both Just and Nothing cases, without having to resort to reading the code or documentation of the function in question.

I see. So is there any reasonable scenario where one should use assertions in Haskell? Like you said, given any function returning a type T I can always Maybe it and avoid assertions altogether, right? Why did the Haskell guys enable it?
– OrenIshShalomFeb 11 at 7:01

4

@OrenIshShalom There's a couple of reasons that exceptions are still part of Haskell. One of them is that Haskell is an old language, and that certain language features are still around for historical or backwards compatibility reasons. Another reason is that you could argue that exceptions are still appropriate in the context of IO, where functions are already impure.
– Mark SeemannFeb 11 at 7:18

@OrenIshShalom, assertions are for checking that your code is correct. In many cases, you can indeed avoid them by carefully ensuring that your invariants are enforced structurally or through the type system. But sometimes you can't, or can't easily, do so. Suppose you have a weight-balanced tree. You may add an assertion to your rebalancing operation(s) to verify that each resulting node is actually balanced appropriately.
– dfeuerFeb 11 at 22:52