Backpacking tips

Daniel Díaz Carrete
3 min readAug 12, 2017

--

This post is about indoor backpacking. To be precise, it contains tips and observations for working with Backpack, Haskell’s new module system.

  • Edward Z. Yang’s thesis is actually a very readable introduction and the diagrams are pretty. See also str-sig and its various implementations to learn how to structure things.
  • Libraries provide modules, and now can also have “holes”: abstract module signatures that are imported by module code. Signature packages, which don’t provide any modules, can be regarded as “made up of holes”.
  • Backpack lets you create modified “copies” of libraries, in which both the libraries’ modules and their “holes” have been renamed.
  • In .cabal files, libraries and other components like tests and executables can now feature a mixins field. Each entry in a mixins field creates a modified “copy” of a library dependency, to be used in the current component. Libraries are identified by their package name (which should be present in the build-depends field).
  • Holes are renamed in the requires clause of an entry in the mixins field. Notice that this also applies to signatures in signature packages.
  • You are not obligated to rename all the modules provided by a library you are “copying”. But what happens if you make two copies of the library? Wouldn’t that create an ambiguity? No, because modules which haven’t been renamed become inaccesible to the current component. See section 5.3 of the thesis, “Thinning and renaming component shapes”.
  • The names of all the “holes” in libraries you intend to use must line up with the names of available implementation modules, and the definitions in the modules must match with everything required by the module signatures.
  • If the name of a signature doesn’t fit naturally with the name of an implementation module, you will need to rename either the signature, the module, or both in the mixins field.
  • If you want to instantiate a “holey” library in two different ways, it’s not good to rename the implementation modules to match the signature. You’ll need instead to rename the “holes” to match the implementation modules , and also — in order to be able to distinguish the instantiations — rename the modules provided by the “holey” library. See section 2.4 of the thesis.
  • Libraries containing implementation modules don’t need to know anything about libraries with “holes”. They just match (or not) when you try to put them together.
  • A module signature can be defined with the exact same name in multiple libraries. This doesn’t cause a conflict, as the definitions are simply merged. Very different from normal modules! Repeated types and functions must be coherent, though. See section 3.3.4 of the thesis, “Signature merging”.
  • “Signature thinning” applies to signature packages, which don’t provide any modules, only signatures. It lets you select just the definitions you need from a potentially very big signature that could be difficult to implement fully. See section 2.7 of the thesis, “Reusing and thinning signatures”. See also this post.
  • An implementation module can provide more things than those strictly required by a signature, and you can access them by importing the module in the usual way.
  • You can use Backpack for renaming modules provided by normal libraries that don’t have any “holes” whatsoever. This would let you rename Data.ByteString to Bytes, for example. In fact, this is a good starting point with Backpack!
  • A limitation: you can’t “fill in” a signature with a module which is defined in the current component. A good workaround for this is putting the module in a convenience library in the same package. Convenience libraries are not visible outside the package in which they are defined.

--

--

No responses yet