{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{- |
Needs generalized instances for IArray.
-}
module Sound.Signal.StrictBlock where

import Data.Array.Unboxed (UArray)
import Data.Array.IArray (IArray, ixmap, bounds, elems, listArray)

-- import qualified Sound.Signal as Signal

import qualified Data.List as List

import Prelude hiding ((++), iterate, foldl)


{-
instance Signal.C T where
   singleton x = Cons 0 [x]
--   unfoldr f = List.unfoldr (Just . f)
--   foldl'    = List.foldl'
   (Cons k x) ++ y = Cons k (x List.++ toChunkList y)
--   mapAccumL = List.mapAccumL
-}


data T a = Cons {
   offset :: Int,
   chunks :: [UArray Int a]
   }

toChunkList :: (IArray UArray a) => T a -> [UArray Int a]
toChunkList (Cons k (x:xs)) =
   ixmap (let (0,n) = bounds x in (0,n-k)) (k+) x
      : xs
toChunkList (Cons 0 []) = []
toChunkList _ =
   error "Sound.Signal.Block: invalid empty structure"

singleton :: (IArray UArray a) => a -> T a
singleton x = Cons 0 [listArray (0,0) [x]]

-- unfoldr :: (a -> (b,a)) -> a -> T b
--   unfoldr f = List.unfoldr (Just . f)

foldl' :: (IArray UArray a) => (acc -> a -> acc) -> acc -> T a -> acc
foldl' f start =
   List.foldl' (\acc -> List.foldl' f acc . elems) start . toChunkList

(++) :: (IArray UArray a) => T a -> T a -> T a
(Cons k x) ++ y = Cons k (x List.++ toChunkList y)

-- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> T x -> (acc, T y)
-- mapAccumL = List.mapAccumL