I was toying with Haskell a few years ago, and I found it unpractical.

Sometimes it turns out you need to do something with IO somewhere, and now you have to change all the functions down the way to use it. \nSimilar issue is lack of exceptions - Haskell just has a type enhanced version of 'return -1' from C. Exceptions should be completely separate from successful execution paths. Throwing exception from a pure function with type like Int -> Int requires changes in everything that uses it. \nCommon Lisp's condition system is much, much better.

The third issue I remember was that all fields' names are global.

All of this makes it very hard to write the minimal working code now and extend it later. Instead, you have to provide scaffolding for possible future changes, or risk having to change everything.

Maybe there's some True Way of using Haskell which doesn't suffer from these issues, but I haven't found it.

>Sometimes it turns out you need to do something with IO somewhere, and now you have to change all the functions down the way to use it.

Que no!

Bloodhound, which is expressly about talking to an outside database, has >500 type signatures. Fewer than 40 have IO in them. You most certainly do not need to add IO to pure code just because something in IO invokes it.

This is why we have things like Functor, monad transformers, etc.

Want to know more?

https://github.com/bitemyapp/learnhaskell