Jezen Thomas

Jezen Thomas

CTO & Co-Founder at Supercede.

Haskell Pattern: Design for Qualified Imports

When you’re writing library code, design for qualified imports.

Let’s say we’re writing a module which is concerned with parsing email addresses. Inside this Email module, a function named parseEmail would be carrying more context in its name than is necessary. The name parse would be sufficient.

When applying our parsing function in some other module, the name needs to be more descriptive so that it is more obvious what kind of thing the parsing function parses.

We also might need to disambiguate this parsing function from another parsing function that may be in scope.

Email.parseEmail is redundant.

parseEmail makes it hard to know where the function is defined.

Email.parse is easy to read.

Email.parse makes it clear what kind of thing we’re parsing.

Email.parse makes it clear where that function is defined.

import Acme.Email qualified as Email -- exports `parse`, not `parseEmail`

main :: IO ()
main = print $ Email.parse "foo@bar.com"

The module describes the context we’re in. Sometimes we need to make that context clearer, and sometimes the context is already clear enough.