{-# LANGUAGE ScopedTypeVariables, TypeFamilies, MultiParamTypeClasses, BangPatterns, GADTs #-}
module Data.RangeMin.Mixed (MixVector, MMixVector, zip, unzip) where

-- import Control.Monad.ST
import Data.RangeMin.Mixed.Mutable
import Data.Vector.Generic hiding (zip, unzip)
import Prelude hiding (zip, unzip)

data MixVector v1 v2 x where
	Mix :: {-# UNPACK #-} !Int -> !(v1 a) -> !(v2 b) -> MixVector v1 v2 (a, b)

type instance Mutable (MixVector v1 v2) = MMixVector (Mutable v1) (Mutable v2)

instance (Vector v1 a, Vector v2 b) => Vector (MixVector v1 v2) (a, b) where
	{-# INLINE unsafeFreeze #-}
	unsafeFreeze (MMix n v1 v2) = do
		v1' <- unsafeFreeze v1
		v2' <- unsafeFreeze v2
		return (Mix n v1' v2')
	basicLength (Mix n _ _) = n
	{-# INLINE basicUnsafeSlice #-}
	basicUnsafeSlice !i !k (Mix _ v1 v2) = 
		Mix k (basicUnsafeSlice i k v1) (basicUnsafeSlice i k v2)
	{-# INLINE basicUnsafeIndexM #-}
	basicUnsafeIndexM (Mix _ v1 v2) !i = do
		a <- basicUnsafeIndexM v1 i
		b <- basicUnsafeIndexM v2 i
		return (a, b)
	{-# INLINE basicUnsafeCopy #-}
	basicUnsafeCopy (MMix _ v1D v2D) (Mix _ v1S v2S) = do
		basicUnsafeCopy v1D v1S
		basicUnsafeCopy v2D v2S

{-# INLINE zip #-}
zip :: (Vector v1 a1, Vector v2 a2) => v1 a1 -> v2 a2 -> MixVector v1 v2 (a1, a2)
zip xs ys = Mix (basicLength xs) xs ys

unzip :: MixVector v1 v2 (a1, a2) -> (v1 a1, v2 a2)
unzip (Mix _ xs ys) = (xs, ys)