| |
Qualified Types and Musical L-Systems
Due: Wed Oct 29 at noon.
Read Chapters 10 and 11 in HSOM.
- We have worked with several different Music
types, such as Music Pitch,
Music (Pitch,Volume), and
Music (Pitch,[NoteAttribute]). In
the end though we usually want our music values to have type
Music (Pitch,[NoteAttribute]), and we find
ourselves having to write coercion functions to do this. What would be
nicer is the following:
Define a type class called StdMusic having a
single method:
toStdMusic :: Music a -> Music (Pitch, [NoteAttribute])
such that toStdMusic can be applied to any
m :: Music T, as long as
T is an instance of
StdMusic, in each case yielding a value of type
Music (Pitch, [NoteAttribute]). Then
define instances of StdMusic for
Pitch, (Pitch, Volume), and
(Pitch,[NoteAttribute]).
The nice thing about this design is that if we have n types we no
longer need to remember n-1 coercion functions -- we can just use
toStdMusic, and in that sense you can view
this as an overloading of the name.
Note: to get this to work in GHC you will need to start GHCi with
certain type extensions enabled, like this:
> ghci -XFlexibleInstances -XTypeSynonymInstances
- Now define a type class called PrimEquiv
with one method:
(===) :: a -> a -> Bool
such that x === y tells us whether or not
"primitive musical values" x and
y are "equivalent" from a "musical point of
view". For example, we would expect all of the following to be
True:
Cs === Df
Note qn Cs === Note (1/4) Df
cs 4 qn === df 4 qn
Note qn (Cs,[Volume 5]) === Note qn (Df, [Volume (2+3)])
To get all this to work, you will need to define instances of
PrimEquiv for
PitchClass, Pitch,
Primitive a, (PitchClass,[NoteAttribute]),
and Music a, although for the latter it should
only work for primitive music values (i.e. an error should occur if
non-primitive values are compared).
- Define an L-System grammar to create some "interesting" music using the
functions defined in Chapter 10.
- Extend the L-System design in Chapter 10 to include a parallel
construction; i.e. add a constructor (:=) to
the LSys data type.
|