The haskell-names package

[Tags: bsd3, library]

For a high-level overview of this package, see

[Skip to ReadMe]


Versions0.1, 0.1.1, 0.1.2, 0.2, 0.2.1, 0.3, 0.3.1, 0.3.2,,,,,,,,, 0.3.3,,, 0.4, 0.4.1, 0.5.0, 0.5.1, 0.5.2, 0.5.3, 0.6.0
Dependenciesaeson, base (==4.*), bytestring, Cabal (>=1.14 && <1.20), containers (>=0.2), data-lens, data-lens-template, filepath (>=1.1), haskell-packages (>=0.2), haskell-src-exts (>=1.14 && <1.16), hse-cpp, mtl, tagged, transformers, traverse-with-class, type-eq, uniplate (>=1.5.1) [details]
AuthorRoman Cheplyaka, Lennart Augustsson
MaintainerRoman Cheplyaka <>
Home page
Source repositoryhead: git clone git://
this: git clone git:// v0.3.1)
UploadedSun Sep 29 13:29:08 UTC 2013 by RomanCheplyaka
UpdatedTue May 5 09:43:55 UTC 2015 by AdamBergmark to revision 1
Downloads7887 total (54 in last 30 days)
0 []
StatusDocs available [build log]
Successful builds reported [all 1 reports]




Maintainers' corner

For package maintainers and hackage trustees

Readme for haskell-names-0.3.1


haskell-names does name and module resolution for haskell-src-exts AST.

Namely, it can do the following:


To install a released version:

  1. Install Cabal and cabal-install from our git repository
  2. cabal install haskell-names hs-gen-iface

If you're building a development version, then you might also need to install development versions of haskell-src-exts, haskell-packages, and hse-cpp.

Module interfaces

hs-gen-iface is a «compiler» that generates interfaces for Haskell modules.

An interface is a JSON file that lists all entities (types, classes, functions etc.) exported by every module. For example, here are a couple of entries from Prelude.names:

    "fixity": null,
    "origin": {
      "name": "map",
      "module": "GHC.Base",
      "package": "base-"
    "entity": "value"
    "fixity": null,
    "origin": {
      "name": "IO",
      "module": "GHC.Types",
      "package": "ghc-prim-"
    "entity": "data"

As you see, each entity is annotated with the module and package where it was originally defined, and also with its fixity. Additionally, class methods, field selectors, and data constructors are annotated with the class or type they belong to.

Generating interfaces

Thanks to haskell-packages, hs-gen-iface is fully integrated with Cabal. To produce and install interface files, pass --haskell-suite -w hs-gen-iface flags to cabal install, for instance

cabal install --haskell-suite -w hs-gen-iface mtl

This assumes that the hs-gen-iface executable is in your PATH. You can specify the full path to hs-gen-iface after -w, too.

Core packages

haskell-names comes with the global package database populated with some core packages:

% hs-gen-iface pkg list --global

Compiling core packages by hand

Suppose you need to compile any of the core packages by hand — for example, to get a different version than the one bundled with haskell-names.

Core packages, such as ghc-prim, integer-simple, and base, are highly GHC-specific and need to be tweaked a bit before they can be processed by haskell-names. Get our modified versions:

Note that Cabal's new dependency solver won't let you install ghc-prim or base easily. There are two ways to work around this:

  1. Use the old solver:

     cabal install --haskell-suite -w hs-gen-iface --solver=topdown
  2. Invoke all the steps manually:

     cabal configure --haskell-suite -w hs-gen-iface
     cabal build
     cabal install --only

Using interfaces

You can parse interface files directly, but a better idea is to use Distribution.HaskellSuite.Packages API (from haskell-packages), combined with the package database NamesDB defined in Language.Haskell.Modules.Interfaces.

Name resolution

There are two approaches to name resolution.

A simpler one is provided by the annotateModule function which annotates the module with scoping information.

A more advanced interface is given by the Language.Haskell.Names.Open module. Its essence is described in the article Open your name resolution. It is, however, very experimental.


Let's say you have a module and you want to find out whether it uses Prelude.head.

import Language.Haskell.Exts.Annotated
import Language.Haskell.Names
import Language.Haskell.Names.Interfaces
import Distribution.HaskellSuite
import Distribution.Simple.Compiler

import Data.Maybe
import Data.List
import Data.Proxy
import qualified Data.Set as Set
import qualified Data.Foldable as Foldable
import Text.Printf
import Control.Applicative
import Control.Monad

main = do

  -- read the program's source from stdin
  source <- getContents

    -- parse the program (using haskell-src-exts)
    ast = fromParseResult $
      parseModuleWithMode defaultParseMode {parseFilename="stdin"} source

  -- get all installed packages (user and global)
  pkgs <-
    (++) <$>
      getInstalledPackages (Proxy :: Proxy NamesDB) UserPackageDB <*>
      getInstalledPackages (Proxy :: Proxy NamesDB) GlobalPackageDB

  headUsages <- evalNamesModuleT (findHeads ast) pkgs

  forM_ headUsages $ \loc ->
    printf "Prelude.head is used at %s\n" (prettyPrint $ srcInfoSpan loc)

  when (null headUsages) $
    printf "Congratulations! Your code doesn't use Prelude.head\n"

-- this is a computation in a ModuleT monad, because we need access to
-- modules' interfaces
findHeads :: Module SrcSpanInfo -> ModuleT Symbols IO [SrcSpanInfo]
findHeads ast = do
  -- first of all, figure out the canonical name of "Prelude.head"
  -- (hint: it's "GHC.List.head")
  Symbols values _types <- fromMaybe (error "Prelude not found") <$> getModuleInfo "Prelude"
    headOrigName =
      fromMaybe (error "Prelude.head not found") $
        -- this looks a bit scary, but we're just walking through all
        -- values defined in Prelude and looking for one with unqualified
        -- name "head"
        [ origName
        | SymValue { sv_origName = origName@(OrigName _pkg (GName _mod "head")) } <- Set.toList values
  -- annotate our ast with name binding information
  annotatedAst <-
      Haskell2010 -- base language
      []          -- set of extensions

    -- get list of all annotations
    annotations = Foldable.toList annotatedAst

    -- look for headOrigName
    headUsages = nub
      [ location
      | Scoped (GlobalValue valueInfo) location <- annotations 
      , sv_origName valueInfo == headOrigName

  return headUsages

Example invocation

% ./find-heads 
one = head [1]
Prelude.head is used at stdin: (1:7) - (1:11)

% ./find-heads
import Prelude hiding (head)
import Data.Text

f = head (pack "foo")
Congratulations! Your code doesn't use Prelude.head

API documentation

See haskell-names haddock documentation.

The two modules you need are:

Other modules are more experimental, less documented, and you probably don't need them anyway.

Known issues

See the list of all issues.