Mezzo
A Haskell library for typesafe music composition
Install / Use
/learn @DimaSamoz/MezzoREADME
Mezzo
Mezzo is a Haskell library and embedded domain-specific language for music description. Its novelty is in the fact that it can enforce various rules of music composition statically, that is, at compile-time. This effectively means that if you write "bad" music, your composition will not compile – think of it as a very strict spell-checker for music.
Getting started
This section explains how to install Mezzo and start using the library.
Prerequisites
Mezzo is a Haskell library with only a few dependencies. The main requirement is GHC 8.0.2: the package uses the latest and greatest features of the Haskell type system so it needs the most up-to-date version of the compiler. If you're using stack, use the lts-8.5 resolver (or higher).
Installation
If using Cabal, run
cabal update
cabal install mezzo
If using Stack, you will need to add the package to your extra-deps in your stack.yaml (as Mezzo is not part of Stackage yet), and then add it normally to your .cabal file dependencies:
extra-deps: [ mezzo-0.3.1.0 ]
build-depends: base >= 4.7 && < 5
, mezzo
Build the file, and you should be good to go.
First composition
Create a new project (e.g. with stack new) with a Main module. Type:
import Mezzo
comp = defScore $ start $ melody :| c :| d :| e :| f :>> g
main :: IO ()
main = renderScore "comp.mid" "First composition" comp
Save, build and execute (e.g. with stack exec <project_name>). You should get a .mid file in the project directory which looks something like this:

To test the correctness checking, change the d note in comp to a b. You should see the following when you save the file:
• Major sevenths are not permitted in melody: C and B
• In the first argument of ‘(:|)’, namely ‘melody :| c :| b’
In the first argument of ‘(:|)’, namely ‘melody :| c :| b :| e’
In the first argument of ‘(:>>)’, namely
‘melody :| c :| b :| e :| f_’
Composing in Mezzo
This section provides more detail on the syntax of Mezzo.
Basic concepts
Music description languages are textual representations of musical pieces, used for note input or transcription. Most MDLs provide ways of inputting notes, rests and ways to combine these into melodies or chords. Mezzo additionally lets users input chords in their symbolic representation, as well as chord progressions using a schematic description of functional harmony.
Literal vs. builder style
Mezzo provides two main ways of creating musical values:
- Literal style: create musical values with explicit constructors of literal values. For example a C natural in octave 4 is written as
pitch _c _na _o4and can be abbreviated to_cn. A quarter note (pitch with duration) is then written asnoteP (pitch _c _na _o4) _quornoteP _cn _qu. Literal values are prefixed with an underscore and can be combined using the constructorspitchandnoteP. - Builder style: create musical values by sequencing their attributes from left to right. This style is more concise, flexible and readable than literal style and is therefore preferred. Creating a middle C quarter note is
c qn, an F sharp dotted sixteenth note in the 5th octave isfs sn'orf sharp sn'. Similarly, a C major chord would bec maj qc, a B flat diminished seventh in first inversion with dotted half duration would beb flat dim7 inv hc'.
The rest of this guide uses the builder style.
Primitives
Notes
Notes are given by their pitch and duration. In builder style, every pitch has an explicit value, consisting of three parts:
- Pitch class: one of
c,d,e,f,g,aorb; determines the position of the note in the octave, a white key on the keyboard. - Accidental: a suffix of the pitch class, one of
f(flat, e.g.bf qn) ors(sharp, e.g.fs qn). Natural accidentals are not specified, socmeans C natural. Accidentals can also be written out as a separate attribute (c sharp qn), or even repeated (for example, double sharps:c sharp sharp qnorcs sharp qn). - Octave: the last component of the value. The default octave is 4, this is unmarked. Lower octaves are marked with
_,__,_3,_4and_5. Higher octaves are marked with','','3and'4. A C natural in octave 2 is thereforec__ qn, a B flat in octave 7 isbf'3 qn.
Durations are written after the pitch. For notes, the value is the first letter of the duration name (eighth, quarter, etc.) followed by n for note, e.g., qn for quarter note. A dotted duration is specified by following the name with a ' (single quote): hn' is a dotted half note, with the length of three quarters.
Rests
Rests are similar to notes, but with r instead of the pitch and an r instead of n in the duration. A quarter rest is r qr and a dotted whole rest is r wr'.
Chords
Chords are given by their root (a pitch), type, inversion and duration: a C major quarter triad in first inversion is c maj inv qc.
- Root: specified the same way as in a note (
c,af'', etc.). - Type: three classes of chords: dyads, triads and tetrads.
- Dyads: A harmonic interval consisting of 2 notes. 5 types possible: minor thirds (
min3), major thirds (maj3), fourths (fourth), fifths (fifth) and octaves (oct). - Triads: 3 pitches separated by thirds. 4 types possible: major (
maj), minor (min), augmented (aug) and diminished (dim), based on the size of the intervals between the pitches. - Tetrads: 4 pitches separated by thirds (the top one is a seventh above the bottom one). 5 types possible: major seventh (
maj7), major-minor/dominant seventh (dom7), minor seventh (min7), half-diminished seventh (hdim7), diminished seventh (dim7).
- Dyads: A harmonic interval consisting of 2 notes. 5 types possible: minor thirds (
- Doubling: dyads and triads can be doubled to become a triad and tetrad respectively. This is done by repeating the bottommost note an octave higher, so a doubled C major third would consist of a C, an E, and another C an octave above. Doubling is specified by a
Dafter the chord type, e.g.fifthD,majDoraugD. - Inversion: all of the types can be followed by a
'and then a separate attributei0,i1,i2ori3to specify zeroth, first, second or third inversion:c maj' i2 qc. Alternatively, theinvattribute can be added (any number of times) to invert a chord once (or any number of times):c maj inv inv qc.
Chord durations end with a c and can be dotted, as before: c min7 qc, f sharp hdim inv wc'.
Composition
Mezzo has two ways of composing music, inspired by Haskore: sequential (melodic) and parallel (harmonic) composition. In addition, Mezzo provides a convenient shorthand input method for melodies.
Harmonic composition
Harmonic composition (:-:) plays two pieces of music at the same time:
g qn :-: e qn :-: c qn
For consistency, pieces should be composed from top voice to the bottom: the above example would therefore play a C major triad. The composed pieces can be any musical composition, as long as the durations of the pieces matches. If this is not the case, the shorter voice has to be padded by rests where necessary.
When using (:-:), both harmonic intervals and harmonic motion are checked for correctness, so it is mainly intended for contrapuntal compositions. For homophonic compositions (where the "voices" are not independent, the top one being the main melody and the bottom ones being the accompaniment), you can use the hom function which does not enforce rules of harmonic motion. For example,
(g qn :|: a qn) :-: (c qn :|: d qn)
would not compile due to a parallel fifth ((:|:) is melodic composition, described in the next section). However,
(g qn :|: a qn) `hom` (c qn :|: d qn)
compiles, as hom only checks for harmonic dissonance.
Melodic composition
Melodic composition (:|:) plays one piece of music after the other:
c qn :|: d qn :|: e qn
The pieces don't have to only be notes or single voices, but the number of voices in the two pieces must match. For example, the code
c qn :|: c maj qc
fails to compile (and unfortunately produces a very cryptic error message), as the first note is only one voice while the chord is three voices. We can remedy this either by explicitly adding rests, or padding the first piece with silent voices, using the functions pad, pad2, `
Related Skills
node-connect
338.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
338.0kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.4kCommit, push, and open a PR
