{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE TypeFamilies           #-}

module Language.Modulators
  ( (#=)
  , (^=)
  ) where

import Language.Notes (Note (Note, getOctave, getTone), Octave, Pitch (..),
                       Tone)

class ModulateOctave a b | a -> b where
  (^=) :: a -> Octave -> b

instance ModulateOctave Note Note where
  ^= :: Note -> Octave -> Note
(^=) Note
note Octave
octave = Note
note { getOctave :: Octave
getOctave = Octave
octave }

instance ModulateOctave [Note] [Note] where
  ^= :: [Note] -> Octave -> [Note]
(^=) [Note]
notes Octave
octave = (Note -> Note) -> [Note] -> [Note]
forall a b. (a -> b) -> [a] -> [b]
map (Note -> Octave -> Note
forall a b. ModulateOctave a b => a -> Octave -> b
^= Octave
octave) [Note]
notes

instance ModulateOctave Tone Note where
  ^= :: Tone -> Octave -> Note
(^=) Tone
tone Octave
octave = Tone -> Pitch -> Octave -> Note
Note Tone
tone Pitch
Flat Octave
octave

instance ModulateOctave [Tone] [Note] where
  ^= :: [Tone] -> Octave -> [Note]
(^=) [Tone]
tones Octave
octave = (Tone -> Note) -> [Tone] -> [Note]
forall a b. (a -> b) -> [a] -> [b]
map (Tone -> Octave -> Note
forall a b. ModulateOctave a b => a -> Octave -> b
^= Octave
octave) [Tone]
tones

class ModulateTone a where
  (#=) :: a -> Tone -> a

instance ModulateTone Note where
  #= :: Note -> Tone -> Note
(#=) Note
note Tone
tone = Note
note { getTone :: Tone
getTone = Tone
tone }

instance ModulateTone [Note] where
  #= :: [Note] -> Tone -> [Note]
(#=) [Note]
notes Tone
tone = (Note -> Note) -> [Note] -> [Note]
forall a b. (a -> b) -> [a] -> [b]
map (Note -> Tone -> Note
forall a. ModulateTone a => a -> Tone -> a
#= Tone
tone) [Note]
notes