{-# LANGUAGE NoImplicitPrelude #-}
module Synthesizer.Interpolation (
T(Cons, margin, func),
Margin(marginOffset, marginNumber),
cons,
number,
offset,
PrefixReader,
getNode,
fromPrefixReader,
constant,
) where
import qualified Synthesizer.State.Signal as Sig
import Control.Monad.Trans.State (StateT(StateT), evalStateT, )
import Control.Monad.Trans.Writer (Writer, writer, runWriter, )
import Control.Applicative (Applicative(pure, (<*>)), (<$>), liftA2, )
import Data.Monoid (Sum(Sum), )
import qualified Test.QuickCheck as QC
import NumericPrelude.Numeric
import NumericPrelude.Base
data T t y =
Cons {
margin :: !Margin,
func :: !(t -> Sig.T y -> y)
}
data Margin =
Margin {
marginNumber :: !Int,
marginOffset :: !Int
}
deriving (Show, Eq)
instance QC.Arbitrary Margin where
arbitrary = liftA2 Margin (abs <$> QC.arbitrary) (abs <$> QC.arbitrary)
cons :: Int -> Int -> (t -> Sig.T y -> y) -> T t y
cons num off =
Cons (Margin num off)
number :: T t y -> Int
number = marginNumber . margin
offset :: T t y -> Int
offset = marginOffset . margin
newtype PrefixReader y a =
PrefixReader (Writer (Sum Int) (StateT (Sig.T y) Maybe a))
instance Functor (PrefixReader y) where
{-# INLINE fmap #-}
fmap f (PrefixReader m) =
PrefixReader (fmap (fmap f) m)
instance Applicative (PrefixReader y) where
{-# INLINE pure #-}
{-# INLINE (<*>) #-}
pure = PrefixReader . pure . pure
(PrefixReader f) <*> (PrefixReader x) =
PrefixReader (liftA2 (<*>) f x)
{-# INLINE getNode #-}
getNode :: PrefixReader y y
getNode =
PrefixReader $ writer (StateT Sig.viewL, Sum 1)
{-# INLINE fromPrefixReader #-}
fromPrefixReader :: String -> Int -> PrefixReader y (t -> y) -> T t y
fromPrefixReader name off (PrefixReader pr) =
let (parser, Sum count) = runWriter pr
in cons count off
(\t xs ->
maybe
(error (name ++ " interpolation: not enough nodes"))
($t)
(evalStateT parser xs))
{-# INLINE constant #-}
constant :: T t y
constant =
fromPrefixReader "constant" 0 (const <$> getNode)