I have been writing in Haskell almost exclusively since the early summer. Before that I was writing in Scala. I have a significant amount of experience in both C# and F#. One of the most frustrating things about learning Haskell is there is not a good map that takes the way things are done in the OO world of Java and .Net to the way things should be done in Haskell. Even for a good developer it can be difficult to make the transition especially for writing high performance, highly concurrent applications.
I am starting this series to document things that I find have worked in Haskell. I don’t claim to be a Haskell expert, but I do build code that ships and works. I tend to use less of the fancy language features than other people and I prefer to write very readable code even if it is slightly more verbose than it might otherwise be. I hope that others can learn from my experience and move along the learning curve faster.
For our inaugural topic I will cover our development environment. We operate in a mixed language environment using Haskell, C++ and a smattering of both Python and R. We develop primarily on vim (I use mvim) on OSX. We deploy code onto custom Gentoo linux running on both our own boxes as well as EC2 machines.
As our codebase grew we quickly started to become frustrated with cabal as there is no notion of recompile all dependencies, so when a change is made in a common package everyone had to manually recompile their packages in the correct order. We evaluated cabal-dev but ultimately decided that it did not meet our needs, primarily due to the fact that we needed good C++ support and wanted more flexibility to add custom steps which did not seem like it was going to be particularly easy using cabal-dev. Ultimately we built our own build system, cabal-waf, using waf. You can find Nathan’s blog post with more details here.
For debugging we have increasingly moved to using a custom build of the RTS which has our own debugging extensions specifically around heap analysis. Most debugging is done through GDB which in and of itself is a terrible experience compared to using Windbg. In the future we will be adding more functionality for debugging as we will need it to debug production issues. I have not found GHCI to be useful for anything other than trivial issues as it runs far to slow. All core applications and libraries are compiled with -Wall and -Werror to catch any potential bugs that they can pickup.
We use our own forked version of the LLVM bindings for Haskell extensively to do code generation. There was functionality we required the depended on type unsafe code that the maintainers did not feel that they wanted, so we maintain our own fork.
It turns out that we have developed our own set of core libraries as many companies do. We will probably release a couple of these in the future. We have our own time library that takes most of its design from Joda Time. I was actually very shocked by how undeveloped this functionality was on Haskell, and we had to do a far amount of work to get complex time manipulation working initially. Apparently we are not the only ones with problems as I have found another implementation that takes its inspiration from .Net’s DateTime.