module Crypto.Lol.Types.IZipVector
( IZipVector, iZipVector, unIZipVector, unzipIZV
) where
import Crypto.Lol.Factored
import Algebra.ZeroTestable as ZeroTestable
import Control.DeepSeq
import Data.Data
import Data.Functor.Trans.Tagged
import Data.Vector as V
newtype IZipVector (m :: Factored) a =
IZipVector {
unIZipVector :: Vector a}
deriving (Show, Eq, NFData, Functor,
Foldable, Traversable, ZeroTestable.C)
type role IZipVector representational representational
iZipVector :: forall m a . (Fact m) => Vector a -> Maybe (IZipVector m a)
iZipVector = let n = proxy totientFact (Proxy::Proxy m)
in \vec -> if n == V.length vec
then Just $ IZipVector vec
else Nothing
unzipIZV :: IZipVector m (a,b) -> (IZipVector m a, IZipVector m b)
unzipIZV (IZipVector v) = let (va,vb) = V.unzip v
in (IZipVector va, IZipVector vb)
repl :: forall m a . (Fact m) => a -> IZipVector m a
repl = let n = proxy totientFact (Proxy::Proxy m)
in IZipVector . V.replicate n
instance (Fact m) => Applicative (IZipVector m) where
pure = repl
(IZipVector f) <*> (IZipVector a) = IZipVector $ V.zipWith ($) f a
instance (ZeroTestable.C a) => ZeroTestable.C (Vector a) where
isZero = V.all isZero