about summary refs log tree commit diff
path: root/website/sandbox/chord-drill-sergeant/src/Theory.elm
diff options
context:
space:
mode:
authorWilliam Carroll <wpcarro@gmail.com>2020-04-11T15·50+0100
committerWilliam Carroll <wpcarro@gmail.com>2020-04-11T15·50+0100
commit3c8bfe85c9fb6dfa064cb1fc5bcc93af46cdd49f (patch)
tree7f5087f6169c51ab6fbe721af0979613015ff0ad /website/sandbox/chord-drill-sergeant/src/Theory.elm
parent52eb456a0f25913c44615c6828562eb19c94393b (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.elm27
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
+                                             }])))