Learn You a Haskell for Great Good! - Miran Lipovaca [39]
Earlier in the chapter, we solved the problem of finding the sum of all odd squares that are smaller than 10,000. Here’s what the solution looks like when put into a function:
oddSquareSum :: Integer
oddSquareSum = sum (takeWhile (<10000) (filter odd (map (^2) [1..])))
With our knowledge of function composition, we can also write the function like this:
oddSquareSum :: Integer
oddSquareSum = sum . takeWhile (<10000) . filter odd $ map (^2) [1..]
It may seem a bit weird at first, but you will get used to this style quickly. There’s less visual noise because we removed the parentheses. When reading this, you can just say that filter odd is applied to the result of map (^2) [1..], then takeWhile (<10000) is applied to the result of that, and finally sum is applied to that result.
Chapter 6. Modules
A Haskell module is essentially a file that defines some functions, types, and type classes. A Has-kell program is a collection of modules.
A module can have many functions and types defined inside it, and it exports some of them. This means that it makes them available for the outside world to see and use.
Having code split up into several modules has many advantages. If a module is generic enough, the functions it exports can be used in a multitude of different programs. If your own code is separated into self-contained modules that don’t rely on each other too much (we also say they are loosely coupled), you can reuse them later. Your code is more manageable when you split it into several parts.
The Haskell standard library is split into modules, and each of them contains functions and types that are somehow related and serve some common purpose. There are modules for manipulating lists, concurrent programming, dealing with complex numbers, and so on. All the functions, types, and type classes that we’ve dealt with so far are part of the Prelude module, which is imported by default.
In this chapter, we’re going to examine a few useful modules and their functions. But first, you need to know how to import modules.
Importing Modules
The syntax for importing modules in a Haskell script is import ModuleName. This must be done before defining any functions, so imports are usually at the top of the file. One script can import several modules—just put each import statement on a separate line.
An example of a useful module is Data.List, which has a bunch of functions for working with lists. Let’s import that module and use one of its functions to create our own function that tells us how many unique elements a list has.
import Data.List
numUniques :: (Eq a) => [a] -> Int
numUniques = length . nub
When you import Data.List, all the functions that Data.List exports become available; you can call them from anywhere in the script. One of those functions is nub, which takes a list and weeds out duplicate elements. Composing length and nub with length . nub produces a function that’s the equivalent of \xs -> length (nub xs).
Note
To search for functions or to find out where they’re located, use Hoogle, which can be found at http://www.haskell.org/hoogle/. It’s a really awesome Haskell search engine that allows you to search by function name, module name, or even type signature.
You can also get access to functions of modules when using GHCi. If you’re in GHCi and you want to be able to call the functions exported by Data.List, enter this:
ghci> :m + Data.List
If you want to access several modules from GHCi, you don’t need to enter :m + several times. You can load several modules at once, as in this example:
ghci> :m + Data.List Data.Map Data.Set
However, if you’ve loaded a script that already imports a module, you don’t need to use :m + to access that module. If you need only a couple of functions from a module, you can selectively import just those functions. For example, here’s how you could import only the nub and sort functions from Data.List:
import Data.List (nub, sort)
You can also choose to import all of the functions of a module except a few select ones. That’s often useful when several modules