Harmonia.Anchor
- Package
- purescript-harmonia
- Repository
- afcondon/purescript-harmonia
Harmonia.Anchor — a chord's scale reading and the operations it unlocks.
A chord in Harmonia is one of two things: a DegreeChord + Key (a chord
that knows where it sits in a scale — its numeral, quality, and any
borrowing) or just a bag of pitches with no reading at all. The Anchor
type names that distinction directly:
Located key dc— the chord carries its scale context.Free— pitches only; no scale to interpret it against.
The grade of an anchor is not stored — it is derived by reading the
recipe against its key (classify). Grade is an ordinal ladder of how much
harmonic leverage the chord affords:
ShiftOnly < Keyed < Diatonic
and each rung permits a nested set of operations (permitted). Nothing here
forbids a chord from being Free — an unlocated chord is a perfectly legal
inhabitant. The type gives leverage (a total classification a caller can
pattern-match exhaustively) without making the "illegal" state
unrepresentable. Rendering — colour, text, greyed-out buttons — is the
caller's job; this module only says what is true, never how to show it.
Pure Prelude/Data.*; builds unchanged on JS and purerl.
#Op Source
data OpThe operations a chord can be asked to undergo. Shift is the floor
(always available); the rest need progressively richer readings. A closed
set: these are program-logic alternatives, so extending them is a
deliberate recompile, never open user data.
Constructors
Instances
#classify Source
classify :: Key -> DegreeChord -> GradeThe v1 judgment. A located chord is Diatonic when it wears no modal-
interchange override and every pitch it realizes falls inside the key's
scale. Otherwise it is Keyed — it still has a tonic to modulate around,
but it is foreign enough that reflavouring it into another mode is
ill-defined (there is no single "same degree" to re-read).
This is deliberately conservative and needs no chord-analyser: an
out-of-scale chord simply drops to Keyed, so downstream operations pass
it through under blame rather than silently mangling it. The place to grow
later is upward — recognising a chromatic chord as a secondary function
(V/x, viio/x) of a phrase degree and promoting it back to Diatonic in
context. That promotion belongs to the phrase, not the lone chord (see
Harmonia.Graded).
#gradeAnchor Source
gradeAnchor :: Anchor -> GradeThe grade of an anchor, derived. Free is always ShiftOnly; a Located
chord is classified against its key.
#chordInScale Source
chordInScale :: Key -> DegreeChord -> BooleanDoes every pitch class of the realized chord lie in the key's scale?
#diatonicQuality Source
diatonicQuality :: Mode -> Numeral -> Boolean -> QualityThe diatonic chord quality on a given degree of a mode, built by stacking thirds within the scale. This is what makes reflavouring real: the same numeral read in a new mode becomes whatever that mode's own harmony makes it — I maj7 in Ionian becomes i m7 in Aeolian, not a transposed Imaj7.
seventh chooses a four-note (true) or three-note (triad) reading, so a
reflavour preserves the chord's size while re-deriving its flavour.