diff options
author | William Carroll <wpcarro@gmail.com> | 2020-04-11T15·50+0100 |
---|---|---|
committer | William Carroll <wpcarro@gmail.com> | 2020-04-11T15·50+0100 |
commit | 3c8bfe85c9fb6dfa064cb1fc5bcc93af46cdd49f (patch) | |
tree | 7f5087f6169c51ab6fbe721af0979613015ff0ad /website/sandbox/chord-drill-sergeant/src/Theory.elm | |
parent | 52eb456a0f25913c44615c6828562eb19c94393b (diff) |
Prefer type alias to type
Elm reminds me of Haskell. In fact, I'm using `haskell-mode` (for now) in Emacs to write my Elm code, and it works reliably. I'm not writing a Haskell app, but if I were, I would define my application Model with the following Haskell code: ```haskell data Model = Model { whitelistedChords :: [Theory.Chord] , selectedChord :: Theory.Chord , isPaused :: Bool , tempo :: Int } ``` When I first modelled my application state, I did something similar. After reading more Elm examples of SPAs, I see that people prefer using type aliases to define records. As far as I know, you cannot do this in Haskell; I believe all types are "tagged" (something about "nominal typing" comes to mind). Anyhow, Elm isn't Haskell; Haskell has cool features like type classes; Elm has cool features like human-readable error messages and exhaustiveness checking for cases. I love Haskell, and I love Elm, and you didn't ask. Anyhow, this commit refactors my records as type aliases instead of types. I think the resulting code is more readable and ergonomic.
Diffstat (limited to 'website/sandbox/chord-drill-sergeant/src/Theory.elm')
-rw-r--r-- | website/sandbox/chord-drill-sergeant/src/Theory.elm | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/website/sandbox/chord-drill-sergeant/src/Theory.elm b/website/sandbox/chord-drill-sergeant/src/Theory.elm index c80fffc39f3c..4a275fa79e1f 100644 --- a/website/sandbox/chord-drill-sergeant/src/Theory.elm +++ b/website/sandbox/chord-drill-sergeant/src/Theory.elm @@ -36,7 +36,11 @@ type Interval = Half | MinorThird {-| A bundle of notes which are usually, but not necessarily harmonious. -} -type Chord = Chord (Note, ChordType, ChordPosition) +type alias Chord = + { note : Note + , chordType : ChordType + , chordPosition : ChordPosition + } {-| Many possible chords exist. This type encodes the possibilities. I am tempted to model these in a more "DRY" way, but I worry that this abstraction @@ -62,7 +66,10 @@ type ChordPosition = First {-| Songs are written in one or more keys, which define the notes and therefore chords that harmonize with one another. -} -type Key = Key (Note, Mode) +type alias Key = + { note : Note + , mode : Mode + } {-| We create "scales" by enumerating the notes of a given key. These keys are defined by the "tonic" note and the "mode". I thought about including Ionian, @@ -160,16 +167,13 @@ applySteps steps note = {-| Return a list of the notes that comprise a `chord` -} notesForChord : Chord -> List Note -notesForChord chord = - case chord of - -- TODO(wpcarro): Use the Position to rotate the chord n times - Chord (note, chordType, _) -> note :: applySteps (intervalsForChordType chordType) note +notesForChord {note, chordType} = + note :: applySteps (intervalsForChordType chordType) note {-| Return the scale for a given `key` -} notesForKey : Key -> List Note -notesForKey key = - case key of - Key (note, mode) -> applySteps (intervalsForMode mode) note +notesForKey {note, mode} = + applySteps (intervalsForMode mode) note {-| Return a list of all of the chords that we know about. -} allChords : List Chord @@ -206,4 +210,7 @@ allChords = notes |> List.Extra.andThen (\note -> chordTypes |> List.Extra.andThen (\chordType -> chordPositions - |> List.Extra.andThen (\chordPosition -> [Chord (note, chordType, chordPosition)]))) + |> List.Extra.andThen (\chordPosition -> [{ note = note + , chordType = chordType + , chordPosition = chordPosition + }]))) |