I encountered a small aesthetic issue in my music project and it has been bugging me for some time.
I have a type data Key = C | D | ... and I can construct a Scale from a Key and a Mode. The Mode distinguishes between e.g. a major and a minor scale.
I can define the Mode type as a function from Key to Scale. In that case the modes will have lowercase names (which is fine) and I can get a Scale like this
aScale = major C
But musicians don't talk like this. They refer to this scale as the C major scale, not the major C scale.
What I want
Ideally I'd want to write
aScale = C major
Is this possible at all?
What I tried
I can make Key a function that constructs a Scale from a Mode, so I can write
aScale = c Major
But I cannot confine Keys to constructing Scales. They are needed for other things as well (e.g. constructing chords). Also Key should be an instance of Show.
I can put the Mode after the Key when I use an extra function (or value constructor):
aScale = scale C major with scale :: Key -> Mode -> Scale
But the extra word scale looks noisy and contrary to its name, scale isn't really concerned with scales. The intelligent part is in major, scale is really just flip ($).
Using a newtype Mode = Major | Minor ... doesn't really change much, except scale needs to be more intelligent:
aScale = scale C Major