Common programming mistakes for Haskell developers to avoid? [closed]

Tag: haskell Author: monkeyist Date: 2009-07-16

In the spirit of the other common mistakes in questions, what are the most common mistakes that Haskell programmers make? I've been teaching myself Haskell for a little while and I am starting to feel comfortable enough with the language to start applying it in the real world.

And another should-be-community-wiki...
This style of question is usually better appreciated as a Community Wiki.
It's impossible to enforce your standard, as there are no system safeguards in place to do so. It is especially difficult to enforce it consistently, as the Java question so eloquently illustrates.
@Imagist: as indicated by Robert Harvey's 5 comments in your own thread, some people are just on a crusade. Community wiki means "community owned", it is not a category and its not a synonym for "discussion" questions. Ignore the community wiki police.
I don't really care if it's community wiki or not, I just want my question answered. Thanks for your support though.

Best Answer

The most common mistake I know of is introducing a space leak through lazy evaluation. There are lots of ways to achieve this mistake, but one that especially nails programmers with other functional-programming experience is to put a result in an accumulating parameter, thinking that the accumulating parameter will take constant space. In many cases the accumulating parameter takes linear space because parameters are not evaluated.

Another common mistake is to forget that let is always recursive. An unintentional

let x = ... x ...

can lead to baffling outcomes.

Most other common bad experiences manifest not as mistakes but as trouble getting programs past the type checker, or difficulty understanding the monadic I/O model. Difficulties with list comprehensions and with do notations occur occasionally.

In general the difficulties faced by beginning Haskell programmers include

  • Large language with many dark corners, especially in the type system
  • Trouble getting programs to compile, especially when they do I/O
  • Doing everything in the IO monad
  • Great difficulty predicting the time and space behavior of lazy functional programs

Other Answer1

A common mistake for beginning Haskell programmers is to forget the difference between constructor and type namespaces. That was such a beginner's mistake that I'm about embarrassed to have my name attached to it, but I'm pretty confident that others will stumble upon that answer when they have a similar problem, so may as well keep it out there.

Other Answer2

The difference between [] and [[]]: the empty list and the list with 1 element, namely the empty list. This one especially pops up in base cases of recursive functions.

Other Answer3

Use non tail-recursive functions or not strict folds occurring to stack overflow.

comments:

This is less true in Haskell than other functional languages. A lot of the time, laziness makes the non-tail versions of functions a better choice (e.g. you can foldr an infinite list, while the tail-recursive foldl will explode every time).
I know it, but head (x:xs) = head xs + 1 won't explode on a list of 1000000 items?
I had tried head'' (x:xs) = let x' = head'' xs in x' `seq` x' + 1, without success. Anyone have any clues?
Switched to accumulating parameter, is there not another way? head''' :: [Int] -> Int head''' = f 0 where f acc [] = acc f acc (x:xs) = f (acc + 1) xs
@ScootyPuff, Both versions works for me, just the accumulating version is faster.

Other Answer4

The notion of an expression is quite confusing to beginners. Take the conditional construct in imperative programming languages. There its just a construct but in Haskell its an expression. So an if conditional must have a matching else and both must yield values of the same type of evaluation.

wrongFunc n = if n > 18
              then 1
              else False

The if block evalutes to an integer where as the else returns a bool. This is a common error as in Haskell they are not just block of statements but expressions.

comments:

I don't see why that's confusing, and I'm a bit of a Haskell newbie. Compare the same thing in a C-like language: you'd have explicit returns, but the return type would need to be either int or bool and it would be an error to return 1 or false depending on the value of the argument.