Haskell School of Music 1.7-1.9

Posted on March 22, 2020

These are some points of reference and notes from the book the haskell school of music chapter one.

1.7 Abstraction³ 1.7.1 Naming 1.7.2 Functional Abstraction 1.7.3 Data Abstraction 1.8 Haskell Equality vs. Musical Equality 1.9 Code Reuse and Modularity

1.7 Abstraction³

The abstraction principle is the idea of separating patterns from the instances in which they appear.

1.7.1 Naming

An example of abstraction and naming might be something like:

pi :: Double
pi = 3.141592653589793

This allows changing the value in one place vs the many places it might appear i a program. In computer music a pitch consists of a pitch class and an octave. In Euterpea “concert A” is represented as

(A,4)

in music this represents the picth class A in the fourth octave. Defining this looks like:

a440, concertA :: (PitchClass, Octave)
a440     = (A,4) -- concert A
concertA = (A,4) -- A440
{- 
    As a note multi line comments in haskell look
    like this.
-}

We can give several names to the same value in haskell which may help think about different representations of the data as in Machine Learning

A larger expression may require writing things more than once:

x :: Float
x = f (pi * r ** 2 ) + g (pi * r ** 2 )

We can abstract this in Haskell by using another expression

area :: Float
area :: pi * r ** 2
x :: Float
x = f area + g area

We can also limit areas scope using a let expression.

x :: Float
x = let area = pi * r ** 2
    in f area + g area

The name for expressions like the one above for 𝜋 is called a binding.

1.7.2 Functional Abstraction

If the original problem looked like:

x :: Float
x = f (pi * r1 ** 2 ) + g (pi * r2 ** 2 )

we could stll abstract this to

x :: Float
x = let areaF r = pi * r ** 2
    in f (areaF r1) + g (areaF r2)

This is called functional abstraction.

Now a bit of music theory. > A note in Euterpea is defined as pitch combined with a duration.

  • A duration is measured in beats.

  • In Euterpea this has type

    Dur
  • One note with duration of 1 beat is called a whole note

  • One note with duration of ½ beat is called a half note

  • This is the smallest performable peace of music in Euterpe besides a rest

  • Its type is MusicPitch

  • There functions typesignatures are as follows.

    note :: Dur -> Pitch -> MusicPitch
    note d p = ???
    rest :: Dur -> MusicPitch
    rest d = ???
    {-Example-}
    note (1/4) (A,4) -- quarter note concert A
    rest  1 -- rest one beat
  • In Euterpea infix operators combine smalle music values into larger ones…

    (:+:) :: MusicPitch -> MusicPitch -> MusicPitch
    (:=:) :: MusicPitch -> MusicPitch -> MusicPitch
    m1 :+: m2 -- plays music pitch m1 and then m2
    m1 :=: m2 -- plays music pitch m1 and m2 simultaneously
  • Euterpea also has a function

    trans :: Int -> Pitch -> Pitch
    trans i p -- this is the pitch that is i semitones higher than p 

1.7.3 Data Abstraction

Representing situations where the number of values is uncertain as a data structure is useful. To add a single element to the front of a list in haskell the following is used:

x : xs
C : [D, Ef] == [C, D, Ef] == C : D : Ef : [] 
{- these are all valid ways of creating lists -}

for a harmonized list we can define a function hList

hList :: Dur -> [Pitch] -> MusicPitch -- type signature
hList [] = rest 0 -- MusicPitch with 0 duration 
hList d (p : ps) = let hNote dp = note d p :=: note d (trans (-3) p)
                   in hNote d p + hList d ps 

Exercise 1.4

mel :: Integer -> Dur -> [Pitch] -> MusicPitch
mel =  let hList :: Integer -> Dur -> [Pitch] -> MusicPitch
                  hList i d [] = rest 0 -- MusicPitch with 0 duration 
                  hList i d (p: ps) = 
                      let hNote :: Integer -> Dur -> Pitch -> MusicPitch 
                          hNote = i d p = note d p :=: note d (trans i p)
                               in hNote i d p :+: hList i d ps
              in hList i d l

1.8 Haskell Equality vs. Musical Equality

Euterpea formally defines musical interpretation so that the difference of adding a MusicPitch with duration 0 is not different from A MusicPitch without.. this leads to the axiom:

m :+: rest 0 ≡ m

1.9 Code Reuse and Modularity

Replacing code with smaller abstractions allows us to reuse code and simplify implementation even though this may require more code it is still clearer than the single use of an expression.