module Frames.Frame where
import Data.Foldable
#if __GLASGOW_HASKELL__ < 800
import Data.Monoid
#endif
import qualified Data.Vector as V
import Data.Vinyl.TypeLevel
import Frames.Rec (Record)
import Frames.RecF (rappend)
data Frame r = Frame { frameLength :: !Int
, frameRow :: Int -> r }
type FrameRec rs = Frame (Record rs)
instance Functor Frame where
fmap f (Frame len g) = Frame len (f . g)
boxedFrame :: Foldable f => f r -> Frame r
boxedFrame xs = Frame (V.length v) (v V.!)
where v = V.fromList (toList xs)
instance Monoid (Frame r) where
mempty = Frame 0 (const $ error "index out of bounds (empty frame)")
Frame l1 f1 `mappend` Frame l2 f2 = Frame (l1+l2) $ \i ->
if i < l1 then f1 i else f2 (i l1)
instance Foldable Frame where
foldMap f (Frame n row) = foldMap (f . row) [0..n1]
foldl' f z (Frame n row) = foldl' ((. row) . f) z [0..n1]
instance Applicative Frame where
pure x = Frame maxBound (const x)
Frame l1 f1 <*> Frame l2 f2 = Frame (min l1 l2) $ ($) <$> f1 <*> f2
instance Monad Frame where
return = pure
Frame l f >>= fb = foldMap (fb . f) [0 .. l 1]
zipFrames :: FrameRec rs -> FrameRec rs' -> FrameRec (rs ++ rs')
zipFrames (Frame l1 f1) (Frame l2 f2) =
Frame (min l1 l2) $ rappend <$> f1 <*> f2