Making the Jump: Advancing Past Beginner Haskell
At certain points in your Haskell development, you might plateau. This can happen to people at many stages, including right at the start. You get used to certain patterns in the language, and it’s hard to know where to go next. This is our first article on how to break out of these plateaus. Specifically, we’ll look at breaking out of a beginner’s plateau. To jump past the simple language constructs, you need to learn how to organize your Haskell code and incorporate other people’s code.
Of course, you can’t make this jump if you’ve never started! Download our Beginners Checklist for some tools on starting out with Haskell. And read our Liftoff Series for some more details on the basic language mechanics.
Organizing Your Project
When I started writing my first Haskell project, it felt like I was trying to hold together steel beams with Elmer’s glue. I installed all my packages system-wide and only tested my code with GHCI and the runghc command. This limited the development of the project and made it hard for me to incorporate anything new.
Generally, you’ll either be building a library for other people to use, or an executable program. And you want to be able to organize everything involved in that so you can coherently run and test what you’ve created. To do this, you need to learn one of the package management tools for Haskell.
The oldest system in common use is Cabal. Cabal allows you to install Haskell packages. It also allows you to organize your project, install executables, and run tests with ease. Check out the user guide for more information on using Cabal on its own.
Cabal has some gotchas though. So if you’re a beginner, I strongly recommend using Stack. Stack adds another layer on top of Cabal, and it simplifies many of Cabal’s difficulties. To learn more about Stack, you can take our free Stack mini-course!
With either of these, there are three main takeaways. You should declare all your dependencies in 1–2 files. The final product of your project, should be explicitly declared in your .cabal file. Finally, you should be able to run all your tests with a single command.
Stack and Cabal both make it easy to bring in dependencies. But how do you know what other libraries you can use, and what their functions are? The main source of Haskell libraries is Hackage. You should get used to the idea of googling Haskell functions, and finding the package you need on Hackage. Once you’ve found a function you want to use, you should get used to this pattern:
- What module is this function is?
- What package is that module part of?
- Add this package to your .cabal file and import the module into your code.
- Compile your code, make sure it works
Sometimes, you’ll need code that isn’t on Hackage (Github, for instance). Stack has some special ways for you to incorporate that code. You’ll need an entry in the stack.yaml file instead of just the .cabal file.
While we’re discussing Hackage, there are some gotchas you should be aware of when perusing Haskell documentation. First, it’s important to keep an eye on the version of the package you’re using. On many occasions, I’ve found a discrepancy between the type I had in my program and the type in the documentation. Typically, I would google the package name, and get a link to the documentation for the wrong version. And types can sometimes change between versions, so that will definitely cause problems!
A useful command is stack list-dependencies. It will show the version number for every package you are currently using. Then compare that number for your package to what is at the top of the Hackage page. If they don’t match, click the contents button in the top right. This will take you to the list of versions, where you can find the one you’re actually using!
Another gotcha can occur when you know a function name and want to find it on Hackage. You’ll import it via a generic sounding module name. And then you’ll go to the documentation for that module and find that all you have is a list of re-exported modules. This can be frustrating, especially when those modules in turn re-export other modules. You have to do a full depth first search to try to find the function you’re after. In this situation, you’ll want help from some other tools.
Hoogle and Hayoo
Hackage does have a search function. But I’ve often had better luck with Hoogle and Hayoo. Both of these are search engines written for finding things on Hackage. They’ll both help you track down the actual module a function comes from.
Hayoo especially does a good job with operators. Oftentimes, a simple google search will help you find a function with a normal sounding name (e.g. split). But Google searches are bad at finding special characters. But if you enter the specific operator in Hayoo, you have a great chance of finding the module you’re looking for!
My last piece of documentation related advice is to learn to use types. In truth, the type of a function is the most important piece of information you need. You can generally bring up GHCI and get the type of an expression. But oftentimes you’ll only see a type synonym that is not understandable. Also, you won’t be able to see the ways in which you can create something of a particular type. If the code and documentation are well organized, you can almost always do this on Hackage. This can help guide your development process so you can fill in missing holes. For more ideas about using types to drive your development, check out this article in our Haskell Brain series!
Haskell is a cool language. But you’ll soon get over the cool factor of functional purity and laziness. Then it’ll be time to get down to business and start writing more serious programs. To do this, you have to master a Haskell package manager. This will help you organize your work. You’ll also have to learn a lot about the organization of Haskell documentation on Hackage.