{- | A design study about how to design signal processors that adapt to a common sample rate. I simplified "Synthesizer.Inference.DesignStudy.Arrow" to this module which uses only Applicative functors. -} module Synthesizer.Inference.DesignStudy.Applicative where import Data.List (intersect) import Control.Applicative (Applicative(..), liftA3, ) data Rates = Rates [Int] | Any deriving Show -- it is a Reader monad with context processing data Processor a = P Rates (Rates -> a) intersectRates :: Rates -> Rates -> Rates intersectRates Any y = y intersectRates x Any = x intersectRates (Rates xs) (Rates ys) = Rates $ intersect xs ys instance Functor Processor where fmap f (P r f0) = P r (f . f0) instance Applicative Processor where pure x = P Any (const x) (P r0 f0) <*> (P r1 f1) = P (intersectRates r0 r1) (\r -> f0 r (f1 r)) runProcessor :: Processor a -> a runProcessor (P r f) = f r -- test processors processor1, processor2, processor3 :: Processor Rates processor1 = P (Rates [44100, 48000]) id processor2 = P Any id processor3 = P (Rates [48000]) id process :: Processor (Rates, Rates, Rates) process = liftA3 (,,) processor1 processor2 processor3 test :: (Rates, Rates, Rates) test = runProcessor process