module Synthesizer.Inference.DesignStudy.Arrow where

{-
  A hint from Haskell cafe about how to design signal processors
  that adapt to a common sample rate.
-}

{-
Date: Fri, 12 Nov 2004 02:59:31 +0900
From: Koji Nakahara <yu-@div.club.ne.jp>
To: haskell-cafe@haskell.org
-}

import Control.Arrow
import Data.List (intersect)
data Rates = Rates [Int] | Any deriving Show
data Processor b c = P Rates (Rates -> b -> c)

-- test Stream
type Stream = String

intersectRates :: Rates -> Rates -> Rates
intersectRates Any y = y
intersectRates x Any = x
intersectRates (Rates xs) (Rates ys) = Rates $ intersect xs ys

instance Arrow Processor where
  arr f = P Any (const f)
  (P r0 f0) >>> (P r1 f1) =
     P (intersectRates r0 r1) (\r -> f1 r . f0 r)
  first (P r0 f) = P r0 (\r (x, s) -> (f r x, s))

runProcessor :: Processor b c -> b -> c
runProcessor (P r f) s = f r s

-- test processors
process, processor1, processor2, processor3 :: Processor String String
processor1 = P (Rates [44100, 48000]) (\r -> ( ++ show r))
processor2 = P Any                    (\r -> ( ++ show r))
processor3 = P (Rates [48000])        (\r -> ( ++ show r))

process = processor1 >>> processor2 >>> processor3

test :: String
test = runProcessor process "bla"