{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
module Synthesizer.ChunkySize.Signal where

import qualified Synthesizer.ChunkySize.Cut as Cut
import qualified Synthesizer.ChunkySize as ChunkySize

import qualified Synthesizer.Generic.Signal as SigG

import qualified Synthesizer.State.Signal as SigS

import qualified Data.StorableVector.Lazy.Pattern as SigStV
import qualified Data.StorableVector.Lazy as Vector
import Foreign.Storable (Storable)

import Control.Monad.Trans.State (runStateT, )

import qualified Data.List.Match as Match
import qualified Data.List as List

import Prelude (Maybe(Just), fst, (.), id, )


class (SigG.Write sig y, Cut.Transform (sig y)) => Write sig y where
   unfoldRN :: ChunkySize.T -> (s -> Maybe (y,s)) -> s -> sig y


instance Storable y => Write Vector.Vector y where
   {-# INLINE unfoldRN #-}
   unfoldRN :: forall s. T -> (s -> Maybe (y, s)) -> s -> Vector y
unfoldRN T
size s -> Maybe (y, s)
f =
      (Vector y, Maybe s) -> Vector y
forall a b. (a, b) -> a
fst ((Vector y, Maybe s) -> Vector y)
-> (s -> (Vector y, Maybe s)) -> s -> Vector y
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
      LazySize -> (s -> Maybe (y, s)) -> s -> (Vector y, Maybe s)
forall b a.
Storable b =>
LazySize -> (a -> Maybe (b, a)) -> a -> (Vector b, Maybe a)
SigStV.unfoldrN
         (T -> LazySize
ChunkySize.toStorableVectorSize T
size) s -> Maybe (y, s)
f

instance Write [] y where
   {-# INLINE unfoldRN #-}
   unfoldRN :: forall s. T -> (s -> Maybe (y, s)) -> s -> [y]
unfoldRN T
size s -> Maybe (y, s)
f =
      [()] -> [y] -> [y]
forall b a. [b] -> [a] -> [a]
Match.take (T -> [()]
ChunkySize.toNullList T
size) ([y] -> [y]) -> (s -> [y]) -> s -> [y]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
      (s -> Maybe (y, s)) -> s -> [y]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
List.unfoldr s -> Maybe (y, s)
f

instance Write SigS.T y where
   {-# INLINE unfoldRN #-}
   unfoldRN :: forall s. T -> (s -> Maybe (y, s)) -> s -> T y
unfoldRN T
size s -> Maybe (y, s)
f =
      T -> T y -> T y
forall sig. Transform sig => T -> sig -> sig
Cut.take T
size (T y -> T y) -> (s -> T y) -> s -> T y
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (s -> Maybe (y, s)) -> s -> T y
forall acc y. (acc -> Maybe (y, acc)) -> acc -> T y
SigS.unfoldR s -> Maybe (y, s)
f


{-# INLINE replicate #-}
replicate :: (Write sig y) =>
   ChunkySize.T -> y -> sig y
replicate :: forall (sig :: * -> *) y. Write sig y => T -> y -> sig y
replicate = (y -> y) -> T -> y -> sig y
forall (sig :: * -> *) y.
Write sig y =>
(y -> y) -> T -> y -> sig y
iterateN y -> y
forall a. a -> a
id

{-# INLINE iterateN #-}
iterateN :: (Write sig y) =>
   (y -> y) -> ChunkySize.T -> y -> sig y
iterateN :: forall (sig :: * -> *) y.
Write sig y =>
(y -> y) -> T -> y -> sig y
iterateN y -> y
f T
size =
   T -> (y -> Maybe (y, y)) -> y -> sig y
forall s. T -> (s -> Maybe (y, s)) -> s -> sig y
forall (sig :: * -> *) y s.
Write sig y =>
T -> (s -> Maybe (y, s)) -> s -> sig y
unfoldRN T
size (\y
y -> (y, y) -> Maybe (y, y)
forall a. a -> Maybe a
Just (y
y, y -> y
f y
y))

{-# INLINE fromState #-}
fromState :: (Write sig y) =>
   ChunkySize.T -> SigS.T y -> sig y
fromState :: forall (sig :: * -> *) y. Write sig y => T -> T y -> sig y
fromState T
size (SigS.Cons StateT s Maybe y
f s
x) =
   T -> (s -> Maybe (y, s)) -> s -> sig y
forall s. T -> (s -> Maybe (y, s)) -> s -> sig y
forall (sig :: * -> *) y s.
Write sig y =>
T -> (s -> Maybe (y, s)) -> s -> sig y
unfoldRN T
size (StateT s Maybe y -> s -> Maybe (y, s)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT StateT s Maybe y
f) s
x