Skip to content

Backpack documentation in the user manual. #7306

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 122 additions & 1 deletion doc/cabal-package.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2171,7 +2171,20 @@ system-dependent values for these fields.

Supported only in GHC 8.2 and later. A list of packages mentioned in the
:pkg-field:`build-depends` field, each optionally accompanied by a list of
module and module signature renamings.
module and module signature renamings. A valid mixin obeys the
following syntax:

::

Mixin ::= PackageName IncludeRenaming
IncludeRenaming ::= ModuleRenaming { "requires" ModuleRenaming }
ModuleRenaming ::=
{- empty -}
| "(" Renaming "," ... "," Renaming ")"
| "hiding" "(" ModuleName "," ... "," ModuleName ")"
Renaming ::=
ModuleName
| ModuleName "as" ModuleName

The simplest mixin syntax is simply the name of a package mentioned in the
:pkg-field:`build-depends` field. For example:
Expand Down Expand Up @@ -3333,6 +3346,114 @@ a few options:
library for all or part of the work. One option is to copy the source
of ``Distribution.Simple``, and alter it for your needs. Good luck.

.. _Backpack:

Backpack
--------

Cabal and GHC jointly support Backpack, an extension to Haskell's module
system which makes it possible to parametrize a package over some
modules, which can be instantiated later arbitrarily by a user. This
means you can write a library to be agnostic over some data
representation, and then instantiate it several times with different
data representations. Like C++ templates, instantiated packages are
recompiled for each instantiation, which means you do not pay any
runtime cost for parametrizing packages in this way. Backpack modules
are somewhat experimental; while fully supported by cabal-install, they are currently
`not supported by Stack <https://github.com/commercialhaskell/stack/issues/2540>`__.

A Backpack package is defined by use of the
:pkg-field:`library:signatures` field, or by (transitive) dependency on
a package that defines some requirements. To define a parametrized
package, define a signature file (file extension ``hsig``) that
specifies the signature of the module you want to parametrize over, and
add it to your Cabal file in the :pkg-field:`library:signatures` field.

.. code-block:: haskell
:caption: .hsig

signature Str where

data Str

concat :: [Str] -> Str

.. code-block:: cabal
:caption: parametrized.cabal

cabal-version: 2.2
name: parametrized

library
build-depends: base
signatures: Str
exposed-modules: MyModule

You can define any number of regular modules (e.g., ``MyModule``) that
import signatures and use them as regular modules.

If you are familiar with ML modules, you might now expect there to be
some way to apply the parametrized package with an implementation of
the ``Str`` module to get a concrete instantiation of the package.
Backpack operates slightly differently with a concept of *mix-in
linking*, where you provide an implementation of ``Str`` simply by
bringing another module into scope with the same name as the
requirement. For example, if you had a package ``str-impl`` that provided a
module named ``Str``, instantiating ``parametrized`` is as simple as
just depending on both ``str-impl`` and ``parametrized``:

.. code-block:: cabal
:caption: combined.cabal

cabal-version: 2.2
name: combined

library
build-depends: base, str-impl, parametrized

Note that due to technical limmitations, you cannot directly define
``Str`` in the ``combined`` library; it must be placed in its own
library (you can use :ref:`Internal Libraries <sublibs>` to conveniently
define a sub-library).

However, a more common situation is that your names don't match up
exactly. The :pkg-field:`library:mixins` field can be used to rename
signatures and modules to line up names as necessary. If you have
a requirement ``Str`` and an implementation ``Data.Text``, you can
line up the names in one of two ways:

* Rename the requirement to match the implementation:
``mixins: parametrized requires (Str as Data.Text)``
* Rename the implementation to match the requirement:
``mixins: text (Data.Text as Str)``

The :pkg-field:`library:mixins` field can also be used to disambiguate
between multiple instantiations of the same package; for each
instantiation of the package, give it a separate entry in mixins with
the requirements and provided modules renamed to be distinct.

.. code-block:: cabal
:caption: .cabal

cabal-version: 2.2
name: double-combined

library
build-depends: base, text, bytestring, parametrized
mixins:
parametrized (MyModule as MyModule.Text) requires (Str as Data.Text),
parametrized (MyModule as MyModule.BS) requires (Str as Data.ByteString)

Intensive use of Backpack sometimes involves creating lots of small
parametrized libraries; :ref:`Internal Libraries <sublibs>` can be used
to define all of these libraries in a single package without having to
create many separate Cabal packages. You may also find it useful to use
:pkg-field:`library:reexported-modules` to reexport instantiated
libraries to Backpack-unware users (e.g., Backpack can be used entirely
as an implementation detail.)

For more information about Backpack, check out the
`GHC wiki page <https://gitlab.haskell.org/ghc/ghc/-/wikis/backpack>`__.

.. include:: references.inc

Expand Down
2 changes: 1 addition & 1 deletion doc/file-format-changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ relative to the respective preceding *published* version.
----------------------

* New :pkg-field:`library:signatures` and :pkg-field:`mixins` fields
added for supporting Backpack_.
added for supporting :ref:`Backpack`.

* New :pkg-field:`build-tool-depends` field added for adding
build-time dependencies of executable components.
Expand Down
2 changes: 0 additions & 2 deletions doc/references.inc
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,3 @@
.. _cpphs: http://projects.haskell.org/cpphs/

.. _ABNF: https://tools.ietf.org/html/rfc5234

.. _Backpack: https://gitlab.haskell.org/ghc/ghc/-/wikis/backpack