Monday, July 18, 2011

fixed lists

I had an unsafe function:


map_signals :: [TrackLang.Control] -> [TrackLang.PitchControl]
    -> ([Signal.Y] -> [Pitch.Degree] -> state -> Score.Event

        -> Derive.Deriver ([Score.Event], state))
    -> state -> Derive.Events -> Derive.Deriver ([Derive.Events], state)

It's unsafe because it looks up each Control and each PitchControl and passes the values back to the given function, and promises the length of [Signal.Y] will be the same as [TrackLang.Control] and likewise for Degree and PitchControl.  But it's just a promise, not a contract, so ghc started complaining about incomplete pattern matches when called like map_signals [a, b, c] [d, e] $ \[a, b, c] [d, e] -> ....  So the fixed-list package fixes that:



map_signals :: (FixedList.FixedList cs, FixedList.FixedList ps) =>
    cs TrackLang.Control -> ps TrackLang.PitchControl
    -> (cs Signal.Y -> ps Pitch.Degree -> state -> Score.Event
        -> Derive.Deriver ([Score.Event], state))
    -> state -> Derive.Events -> Derive.Deriver ([Derive.Events], state)

Now 'ps' and 'cs' are specified to have the same lengths, and no more warnings.  They get called almost the same:


map_signals (a :. b :. c :. Nil) (d :. e :. Nil) $
    \(a :. b :. c :. Nil) (d :. e :. Nil) -> ...


I wasn't too worried about type errors since the lists and patterns are adjacent, but it's a neat trick anyway.

No comments:

Post a Comment