Music in Haskell
Music Suite is a language for describing music, based on Haskell.
There are two ways of setting up the development environment:
Install the Nix package manager. We recommend using 2.3.1 or later.
Enter environment using:
nix-shell --pure
All build commands should be run in the Nix shell. You can exit the Nix shell using Ctrl-D
.
Install the following.
Make sure that lilypond
timidity
and ghcup
are available your shell environment (e.g. by adding them to PATH
).
Use ghcup
to install GHC:
ghcup install 8.10.4
$ cabal update
$ cabal build
To run all tests except doctests (see below):
$ cabal test --test-show-details=streaming --test-options=--color=always
To run individual tests:
$ cabal run TEST_NAME -- TEST_ARGS...
e.g.
$ cabal run music-suite-test-xml-parser
Some tests have expected output, stored in test/regression
.
If the output of these tests have changed, the diff should be manually inspected to assure that the new output is in fact correct. This may be because:
*.ly
output file that does not affect the appearance of the printed music.To identify the latter it may be necessar to run lilypond
or timidity
on both the old and new versions of the output file. To do this manually after a failure.
cabal test music-suite-test-regression --test-options=--color=always
lilypond
(for *.ly
files) or timidity
(for *.mid
files).cabal test music-suite-test-regression --test-options=--color=always --test-options=--accept
lilypond
or timidity
as before.test/regression
.Note: after running
--accept
, you can usegit diff --name-only test/regression
to get a list of changed files, assuming the repo was clean before.
Music Suite makes use of doctests.
You can pass any file or directory. For example to test src/Music/Pitch
:
$ cabal build music-suite && cabal exec doctester --package music-suite -- src/Music/Pitch
To test a single file:
$ cabal build music-suite && cabal exec doctester --package music-suite -- src/Music/Score/Meta.hs
To run all doctests use (Nix only):
$ doctests
$ cabal build music-suite && cabal exec --package music-suite ghci
or
$ cabal repl
See these instructions.
The output appears in docs/build
. You can point a HTTP server to this directory.
$ cabal haddock
$ cabal exec runhaskell -- examples/chopin.hs -f ly -o t.ly
To replicate all steps run by the CI (Nix only), run:
$ ci
We use Nix to pin the version of GHC and Cabal freeze files to pin the
version of all Haskell dependencies. This describes how to upgrade GHC.
Because GHC pins a version of the Haskell base library, GHC and the Cabal dependencies need to be upgraded together. This is the recommended workflow:
default.nix
$ nix-prefetch-url --unpack <url>
to obtain the hash (and verify)ghc-version
field in cabal.project
to whatever is printed by ghc --version
reject-unconstrained-dependencies
in cabal.project
index-state
in Cabal config to a recent timecabal update
rm cabal.project.freeze
cabal freeze
cabal test
to check that compiling/testing works (and fix errors)reject-unconstrained-dependencies
reject-unconstrained-dependencies
in cabal.project
music-suite.cabal
index-state
in Cabal config to a recent timecabal freeze
cabal test
to check that compiling/testing works (and fix errors)reject-unconstrained-dependencies
The high-level DSL:
Music.Time
: high-level DSL for time and rhythmMusic.Pitch
: high-level DSL for pitch (common, scientific)Music.Dynamics
: high-level DSL for dynamicsMusic.Parts
: high-level DSL for instruments and partsMusic.Prelude
: prelude/standard library for the Music Suite DSLThe notation DSL:
Music.Notation.Standard
: DSL for representing Common/Western music notationImport & Export:
Data.Music.Lilypond
: AST, parsing and pretty-printing for the Lilypond languageData.Music.MusicXml
: AST, parsing and pretty-printing for MusicXMLUtility
Control.*
: miscellaneous algorithms and utilitiesData.*
: miscellaneous data structures