packages feed

fixed-vector 0.2.0.0 → 0.3.0.0

raw patch · 10 files changed

+780/−619 lines, 10 filesdep ~base

Dependency ranges changed: base

Files

Data/Vector/Fixed.hs view
@@ -1,10 +1,4 @@-{-# LANGUAGE EmptyDataDecls        #-}-{-# LANGUAGE TypeFamilies          #-}-{-# LANGUAGE Rank2Types            #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE ScopedTypeVariables   #-}+{-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Generic API for vectors with fixed length. --@@ -46,13 +40,15 @@     -- ** Functions   , replicate   , replicateM-  , basis   , generate   , generateM+  , unfoldr+  , basis     -- * Modifying vectors     -- ** Transformations   , head   , tail+  , (!)     -- ** Comparison   , eq     -- ** Maps@@ -93,9 +89,10 @@   , VecList   ) where -import Data.Vector.Fixed.Internal-import Data.Vector.Fixed.Cont     (VecList)+import Data.Vector.Fixed.Internal.Arity+import Data.Vector.Fixed.Cont     (VecList,Vector(..),VectorN,Dim,length) import qualified Data.Vector.Fixed.Cont as C+import Data.Vector.Fixed.Internal  import qualified Prelude as P import Prelude hiding ( replicate,map,zipWith,maximum,minimum,and,or,all,any@@ -103,429 +100,31 @@                       , head,tail,mapM,mapM_,sequence,sequence_                       ) ---------------------------------------------------------------------- Generic functions--------------------------------------------------------------------- TODO: does not fuse!---- | Generic function for construction of arbitrary vectors. It---   represents partially constructed vector where /n/ is number of---   uninitialized elements, /v/ is type of vector and /a/ element type.------   Uninitialized vector could be obtained from 'con' and vector---   elements could be added from left to right using '|>' operator.---   Finally it could be converted to vector using 'vec' function.------   Construction of complex number which could be seen as 2-element vector:------   >>> import Data.Complex---   >>> vec $ con |> 1 |> 3 :: Complex Double---   1.0 :+ 3.0-newtype New n v a = New (Fn n a (v a))---- | Convert fully applied constructor to vector-vec :: New Z v a -> v a-{-# INLINE vec #-}-vec (New v) = v---- | Seed constructor-con :: Vector v a => New (Dim v) v a-{-# INLINE con #-}-con = f2n construct---- | Apply another element to vector-(|>) :: New (S n) v a -> a -> New n v a-{-# INLINE  (|>) #-}-New f |> a = New (f a)-infixl 1 |>--f2n :: Fun n a (v a) -> New n v a-{-# INLINE f2n #-}-f2n (Fun f) = New f--------------------------------------------------------------------- -- $smallDim -- -- Constructors for vectors with small dimensions. -mk1 :: (Vector v a, Dim v ~ C.N1) => a -> v a-mk1 a1 = C.vector $ C.mk1 a1-{-# INLINE mk1 #-} -mk2 :: (Vector v a, Dim v ~ C.N2) => a -> a -> v a-mk2 a1 a2 = C.vector $ C.mk2 a1 a2-{-# INLINE mk2 #-} -mk3 :: (Vector v a, Dim v ~ C.N3) => a -> a -> a -> v a-mk3 a1 a2 a3 = C.vector $ C.mk3 a1 a2 a3-{-# INLINE mk3 #-}--mk4 :: (Vector v a, Dim v ~ C.N4) => a -> a -> a -> a -> v a-mk4 a1 a2 a3 a4 = C.vector $ C.mk4 a1 a2 a3 a4-{-# INLINE mk4 #-}--mk5 :: (Vector v a, Dim v ~ C.N5) => a -> a -> a -> a -> a -> v a-mk5 a1 a2 a3 a4 a5 = C.vector $ C.mk5 a1 a2 a3 a4 a5-{-# INLINE mk5 #-}------------------------------------------------------------------------ | Replicate value /n/ times.------   Examples:------   >>> import Data.Vector.Fixed.Boxed (Vec2)---   >>> replicate 1 :: Vec2 Int---   fromList [1,1]------   >>> replicate 2 :: (Double,Double,Double)---   (2.0,2.0,2.0)------   >>> import Data.Vector.Fixed.Boxed (Vec)---   >>> replicate "foo" :: Vec N5 String---   fromList ["foo","foo","foo","foo","foo"]-replicate :: Vector v a => a -> v a-{-# INLINE replicate #-}-replicate-  = C.vector . C.replicate---- | Execute monadic action for every element of vector.------   Examples:------   >>> import Data.Vector.Fixed.Boxed (Vec2,Vec3)---   >>> replicateM (Just 3) :: Maybe (Vec3 Int)---   Just fromList [3,3,3]---   >>> replicateM (putStrLn "Hi!") :: IO (Vec2 ())---   Hi!---   Hi!---   fromList [(),()]-replicateM :: (Vector v a, Monad m) => m a -> m (v a)-{-# INLINE replicateM #-}-replicateM-  = C.vectorM . C.replicateM------------------------------------------------------------------------ | Unit vector along Nth axis. If index is larger than vector---   dimensions returns zero vector.------   Examples:------   >>> import Data.Vector.Fixed.Boxed (Vec3)---   >>> basis 0 :: Vec3 Int---   fromList [1,0,0]---   >>> basis 1 :: Vec3 Int---   fromList [0,1,0]---   >>> basis 3 :: Vec3 Int---   fromList [0,0,0]-basis :: forall v a. (Vector v a, Num a) => Int -> v a-{-# INLINE basis #-}-basis = C.vector . C.basis------------------------------------------------------------------------ | Generate vector from function which maps element's index to its---   value.------   Examples:------   >>> import Data.Vector.Fixed.Unboxed (Vec)---   >>> generate (^2) :: Vec N4 Int---   fromList [0,1,4,9]-generate :: forall v a. (Vector v a) => (Int -> a) -> v a-{-# INLINE generate #-}-generate = C.vector . C.generate---- | Generate vector from monadic function which maps element's index---   to its value.-generateM :: forall m v a. (Monad m, Vector v a) => (Int -> m a) -> m (v a)-{-# INLINE generateM #-}-generateM = C.vectorM . C.generateM------------------------------------------------------------------------ | First element of vector.------   Examples:------   >>> import Data.Vector.Fixed.Boxed (Vec3)---   >>> let x = mk3 1 2 3 :: Vec3 Int---   >>> head x---   1-head :: (Vector v a, Dim v ~ S n) => v a -> a-{-# INLINE head #-}-head = C.runContVec C.head . C.cvec----------------------------------------------------------------------- | Tail of vector.------   Examples:------   >>> import Data.Complex---   >>> tail (1,2,3) :: Complex Double---   2.0 :+ 3.0-tail :: (Vector v a, Vector w a, Dim v ~ S (Dim w))-     => v a -> w a-{-# INLINE tail #-}-tail = C.vector . C.tail . C.cvec------------------------------------------------------------------------ | Left fold over vector-foldl :: Vector v a => (b -> a -> b) -> b -> v a -> b-{-# INLINE foldl #-}-foldl f x = C.runContVec (C.foldl f x)-          . C.cvec---- | Left fold over vector-foldr :: Vector v a => (a -> b -> b) -> b -> v a -> b-{-# INLINE foldr #-}-foldr f x = C.runContVec (C.foldr f x)-          . C.cvec---- | Left fold over vector-foldl1 :: (Vector v a, Dim v ~ S n) => (a -> a -> a) -> v a -> a-{-# INLINE foldl1 #-}-foldl1 f = C.runContVec (C.foldl1 f)-         . C.cvec---- | Left fold over vector-ifoldr :: Vector v a => (Int -> a -> b -> b) -> b -> v a -> b-{-# INLINE ifoldr #-}-ifoldr f x = C.runContVec (C.ifoldr f x)-           . C.cvec---- | Left fold over vector. Function is applied to each element and---   its index.-ifoldl :: Vector v a => (b -> Int -> a -> b) -> b -> v a -> b-{-# INLINE ifoldl #-}-ifoldl f z = C.runContVec (C.ifoldl f z)-           . C.cvec---- | Monadic fold over vector.-foldM :: (Vector v a, Monad m) => (b -> a -> m b) -> b -> v a -> m b-{-# INLINE foldM #-}-foldM f x v = foldl go (return x) v-  where-    go m a = do b <- m-                f b a---- | Left monadic fold over vector. Function is applied to each element and---   its index.-ifoldM :: (Vector v a, Monad m) => (b -> Int -> a -> m b) -> b -> v a -> m b-{-# INLINE ifoldM #-}-ifoldM f x v = ifoldl go (return x) v-  where-    go m i a = do { b <- m; f b i a }------------------------------------------------------------------------ | Sum all elements in the vector.-sum :: (Vector v a, Num a) => v a -> a-sum = C.runContVec C.sum . C.cvec-{-# INLINE sum #-}---- | Maximal element of vector.------   Examples:------   >>> import Data.Vector.Fixed.Boxed (Vec3)---   >>> let x = mk3 1 2 3 :: Vec3 Int---   >>> maximum x---   3-maximum :: (Vector v a, Dim v ~ S n, Ord a) => v a -> a-maximum = C.runContVec C.maximum . C.cvec-{-# INLINE maximum #-}---- | Minimal element of vector.------   Examples:------   >>> import Data.Vector.Fixed.Boxed (Vec3)---   >>> let x = mk3 1 2 3 :: Vec3 Int---   >>> minimum x---   1-minimum :: (Vector v a, Dim v ~ S n, Ord a) => v a -> a-minimum = C.runContVec C.minimum . C.cvec-{-# INLINE minimum #-}---- | Conjunction of all elements of a vector.-and :: (Vector v Bool) => v Bool -> Bool-and = C.runContVec C.and . C.cvec-{-# INLINE and #-}---- | Disjunction of all elements of a vector.-or :: (Vector v Bool) => v Bool -> Bool-or = C.runContVec C.or . C.cvec-{-# INLINE or #-}---- | Determines whether all elements of vector satisfy predicate.-all :: (Vector v a) => (a -> Bool) -> v a -> Bool-all f = C.runContVec (C.all f) . C.cvec-{-# INLINE all #-}---- | Determines whether any of element of vector satisfy predicate.-any :: (Vector v a) => (a -> Bool) -> v a -> Bool-any f = C.runContVec (C.any f) . C.cvec-{-# INLINE any #-}----------------------------------------------------------------------- | Test two vectors for equality.+--------------------------------------------------------------------------------+-- We are trying to be clever with indexing here. It's not possible to+-- write generic indexing function. For example it's necessary O(n)+-- for VecList. It's however possible to write O(1) indexing for some+-- vectors and we trying to use such functions where possible. -----   Examples:+-- We try to use presumable more efficient basicIndex -----   >>> import Data.Vector.Fixed.Boxed (Vec2)---   >>> let v0 = basis 0 :: Vec2 Int---   >>> let v1 = basis 1 :: Vec2 Int---   >>> v0 `eq` v0---   True---   >>> v0 `eq` v1---   False-eq :: (Vector v a, Eq a) => v a -> v a -> Bool-{-# INLINE eq #-}-eq v w = C.runContVec (C.foldl (&&) True)-       $ C.zipWith (==) (C.cvec v) (C.cvec w)----------------------------------------------------------------------- | Map over vector-map :: (Vector v a, Vector v b) => (a -> b) -> v a -> v b-{-# INLINE map #-}-map f = C.vector-      . C.map f-      . C.cvec---- | Evaluate every action in the vector from left to right.-sequence :: (Vector v a, Vector v (m a), Monad m) => v (m a) -> m (v a)-{-# INLINE sequence #-}-sequence = mapM id---- | Evaluate every action in the vector from left to right and ignore result-sequence_ :: (Vector v (m a), Monad m) => v (m a) -> m ()-{-# INLINE sequence_ #-}-sequence_ = mapM_ id----- | Monadic map over vector.-mapM :: (Vector v a, Vector v b, Monad m) => (a -> m b) -> v a -> m (v b)-{-# INLINE mapM #-}-mapM f = C.vectorM-       . C.mapM f-       . C.cvec---- | Apply monadic action to each element of vector and ignore result.-mapM_ :: (Vector v a, Monad m) => (a -> m b) -> v a -> m ()-{-# INLINE mapM_ #-}-mapM_ f = foldl (\m a -> m >> f a >> return ()) (return ())----- | Apply function to every element of the vector and its index.-imap :: (Vector v a, Vector v b) =>-    (Int -> a -> b) -> v a -> v b-{-# INLINE imap #-}-imap f = C.vector-       . C.imap f-       . C.cvec---- | Apply monadic function to every element of the vector and its index.-imapM :: (Vector v a, Vector v b, Monad m) =>-    (Int -> a -> m b) -> v a -> m (v b)-{-# INLINE imapM #-}-imapM f = C.vectorM-        . C.imapM f-        . C.cvec---- | Apply monadic function to every element of the vector and its---   index and discard result.-imapM_ :: (Vector v a, Monad m) => (Int -> a -> m b) -> v a -> m ()-{-# INLINE imapM_ #-}-imapM_ f = ifoldl (\m i a -> m >> f i a >> return ()) (return ())----------------------------------------------------------------------- | Zip two vector together using function.+--  1. It should not interfere with deforestation. So we should+--     rewrite only when deforestation rule already fired.+--     (starting from phase 1). -----   Examples:+--  2. Creation of vector is costlier than generic indexing so we should+--     apply rule only when vector is created anyway -----   >>> import Data.Vector.Fixed.Boxed (Vec3)---   >>> let b0 = basis 0 :: Vec3 Int---   >>> let b1 = basis 1 :: Vec3 Int---   >>> let b2 = basis 2 :: Vec3 Int---   >>> let vplus x y = zipWith (+) x y---   >>> vplus b0 b1---   fromList [1,1,0]---   >>> vplus b0 b2---   fromList [1,0,1]---   >>> vplus b1 b2---   fromList [0,1,1]-zipWith :: (Vector v a, Vector v b, Vector v c)-        => (a -> b -> c) -> v a -> v b -> v c-{-# INLINE zipWith #-}-zipWith f v u = C.vector-              $ C.zipWith f (C.cvec v) (C.cvec u)---- | Zip two vector together using monadic function.-zipWithM :: (Vector v a, Vector v b, Vector v c, Monad m)-         => (a -> b -> m c) -> v a -> v b -> m (v c)-{-# INLINE zipWithM #-}-zipWithM f v u = C.vectorM-               $ C.zipWithM f (C.cvec v) (C.cvec u)---- | Zip two vector together using function which takes element index---   as well.-izipWith :: (Vector v a, Vector v b, Vector v c)-         => (Int -> a -> b -> c) -> v a -> v b -> v c-{-# INLINE izipWith #-}-izipWith f v u = C.vector-               $ C.izipWith f (C.cvec v) (C.cvec u)---- | Zip two vector together using monadic function which takes element---   index as well..-izipWithM :: (Vector v a, Vector v b, Vector v c, Monad m)-          => (Int -> a -> b -> m c) -> v a -> v b -> m (v c)-{-# INLINE izipWithM #-}-izipWithM f v u = C.vectorM-                $ C.izipWithM f (C.cvec v) (C.cvec u)----------------------------------------------------------------------- | Convert between different vector types-convert :: (Vector v a, Vector w a, Dim v ~ Dim w) => v a -> w a-{-# INLINE convert #-}-convert = C.vector . C.cvec---- | Convert vector to the list-toList :: (Vector v a) => v a -> [a]-toList = foldr (:) []+-- In order to avoid firing this rule on implementation of (!) it has+-- been necessary to move definition of all functions to internal module. --- | Create vector form list. Will throw error if list is shorter than---   resulting vector.-fromList :: (Vector v a) => [a] -> v a-{-# INLINE fromList #-}-fromList = C.vector . C.fromList+{-# RULES+"fixed-vector:index/basicIndex"[1] forall vv i.+  runIndex i (C.cvec vv) = C.basicIndex vv i+ #-}
Data/Vector/Fixed/Boxed.hs view
@@ -18,7 +18,7 @@ import Prelude hiding (length,replicate,zipWith,map,foldl)  import Data.Vector.Fixed-import Data.Vector.Fixed.Internal+import Data.Vector.Fixed.Internal.Arity import Data.Vector.Fixed.Mutable  @@ -78,10 +78,12 @@ type instance DimM (MVec n) = n  instance (Arity n) => Vector (Vec n) a where-  construct = constructVec-  inspect   = inspectVec-  {-# INLINE construct #-}-  {-# INLINE inspect   #-}+  construct  = constructVec+  inspect    = inspectVec+  basicIndex = index+  {-# INLINE construct  #-}+  {-# INLINE inspect    #-}+  {-# INLINE basicIndex #-} instance (Arity n) => VectorN Vec n a  instance (Arity n, Eq a) => Eq (Vec n a) where
Data/Vector/Fixed/Cont.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances     #-} {-# LANGUAGE FlexibleContexts      #-}@@ -8,8 +7,13 @@ -- | -- Continuations-based API module Data.Vector.Fixed.Cont (+    -- * Vector type class+    Dim+  , Vector(..)+  , VectorN+  , length     -- * Vector as continuation-    ContVecT+  , ContVecT   , ContVec     -- ** Synonyms for small numerals   , N1@@ -25,6 +29,7 @@   , replicateM   , generate   , generateM+  , unfoldr   , basis     -- ** Constructors   , mk1@@ -39,6 +44,7 @@   , imapM   , tail   , cons+  , changeMonad     -- ** Zips   , zipWith   , izipWith@@ -51,6 +57,7 @@   , runContVec     -- ** Getters   , head+  , index     -- ** Vector construction   , vector   , vectorM@@ -75,13 +82,49 @@   ) where  import Control.Applicative-import Data.Vector.Fixed.Internal+import Data.Complex (Complex(..))+import Data.Vector.Fixed.Internal.Arity+import Data.Vector.Fixed.Internal.Id import Prelude hiding ( replicate,map,zipWith,maximum,minimum,and,or,any,all                       , foldl,foldr,foldl1,length,sum                       , head,tail,mapM,mapM_,sequence,sequence_                       ) + ----------------------------------------------------------------+-- Type class for fixed vectors+----------------------------------------------------------------++-- | Size of vector expressed as type-level natural.+type family Dim (v :: * -> *)++-- | Type class for vectors with fixed length.+class Arity (Dim v) => Vector v a where+  -- | N-ary function for creation of vectors.+  construct :: Fun (Dim v) a (v a)+  -- | Deconstruction of vector.+  inspect   :: v a -> Fun (Dim v) a b -> b+  -- | Optional more efficient implementation of indexing. Shouldn't+  --   be used directly, use 'Data.Vector.Fixed.!' instead.+  basicIndex :: v a -> Int -> a+  basicIndex v i = runContVec (index i) (cvec v)+  {-# INLINE basicIndex #-}++-- | Vector parametrized by length. In ideal world it should be:+--+-- > forall n. (Arity n, Vector (v n) a, Dim (v n) ~ n) => VectorN v a+--+-- Alas polymorphic constraints aren't allowed in haskell.+class (Vector (v n) a, Dim (v n) ~ n) => VectorN v n a++-- | Length of vector. Function doesn't evaluate its argument.+length :: forall v a. Arity (Dim v) => v a -> Int+{-# INLINE length #-}+length _ = arity (undefined :: Dim v)++++---------------------------------------------------------------- -- Cont. vectors and their instances ---------------------------------------------------------------- @@ -101,8 +144,25 @@   {-# INLINE pure  #-}   {-# INLINE (<*>) #-} +-- | Change monad type for the continuation vector.+changeMonad :: (Monad p, Monad m, Arity n)+            => (forall x. p x -> x) -- ^ Function to extract result from monad+            -> ContVecT p n a -> ContVecT m n a+{-# INLINE changeMonad #-}+changeMonad run (ContVecT cont)+  = ContVecT $ convertCont run return cont +convertCont :: (Arity n)+            => (b -> c)+            -> (c -> b)+            -> (Fun n a b -> b)+            -> (Fun n a c -> c)+{-# INLINE convertCont #-}+convertCont fB2C fC2B cont = \funC ->+  fB2C $ cont (fmap fC2B funC) ++ ---------------------------------------------------------------- -- Construction ----------------------------------------------------------------@@ -110,7 +170,7 @@ -- | Convert regular vector to continuation cvec :: (Vector v a, Dim v ~ n, Monad m) => v a -> ContVecT m n a cvec v = ContVecT (inspect v)-{-# INLINE[1] cvec #-}+{-# INLINE[0] cvec #-}  -- | Convert list to continuation-based vector. Will throw error if --   list is shorter than resulting vector.@@ -147,6 +207,7 @@  data T_replicate n = T_replicate + -- | Generate vector from function which maps element's index to its value. generate :: forall m n a. (Arity n) => (Int -> a) -> ContVecT m n a {-# INLINE generate #-}@@ -167,6 +228,17 @@  newtype T_generate n = T_generate Int +-- | Unfold vector.+unfoldr :: forall m n b a. Arity n => (b -> (a,b)) -> b -> ContVecT m n a+{-# INLINE unfoldr #-}+unfoldr f b0 = ContVecT $ \(Fun fun) ->+  apply (\(T_unfoldr b) -> let (a,b') = f b in (a, T_unfoldr b'))+        (T_unfoldr b0 :: T_unfoldr b n)+         fun++newtype T_unfoldr b n = T_unfoldr b++ -- | Unit vector along Nth axis. basis :: forall m n a. (Num a, Arity n) => Int -> ContVecT m n a {-# INLINE basis #-}@@ -361,11 +433,6 @@ vectorM = runContVecT construct {-# INLINE[1] vectorM #-} -{-# RULES "cvec/vector"-   forall x. cvec (vector x) = x-  #-}-- -- | Finalizer function for getting head of the vector. head :: forall n a. Arity (S n) => Fun (S n) a a {-# INLINE head #-}@@ -375,7 +442,25 @@  data T_head a n = T_head (Maybe a) +-- | /O(n)/ Get value at specified index.+index :: forall n a. Arity n => Int -> Fun n a a+index n+  | n < 0     = error "Data.Vector.Fixed.Cont.index: index out of range"+  | otherwise = Fun $ accum+     (\(T_Index x) a -> T_Index $ case x of+                          Left  0 -> Right a+                          Left  i -> Left (i - 1)+                          r       -> r+     )+     (\(T_Index x) -> case x of+                        Left  _ -> error "Data.Vector.Fixed.index: index out of range"+                        Right a -> a+     )+     ( T_Index (Left n) :: T_Index a n) +newtype T_Index a n = T_Index (Either Int a)++ -- | Left fold over continuation vector. foldl :: forall n a b. Arity n       => (b -> a -> b) -> b -> Fun n a b@@ -480,6 +565,37 @@   ----------------------------------------------------------------+-- Deforestation+----------------------------------------------------------------++-- Deforestation uses following assertion: if we convert continuation+-- to vector and immediately back to the continuation we can eliminate+-- intermediate vector. This optimization can however turn+-- nonterminating programs into terminating.+--+-- > runContVec head $ cvec $ vector $ mk2 () ⊥+--+-- If intermediate vector is strict in its elements expression above+-- evaluates to ⊥ too. But if we apply rewrite rule resuling expression:+--+-- > runContVec head $ mk2 () ⊥+--+-- will evaluate to () since ContVec is not strict in its elements.+-- It has been considered acceptable.+--+--+-- In order to get rule fire reliably (it still doesn't). `vector' in+-- inlined starting from phase 1. `cvec' is inlined even later (only+-- during phase 0) because it need to participate in rewriting of+-- indexing functions.+++{-# RULES+"cvec/vector" forall v.+  cvec (vector v) = changeMonad runID v+  #-}++---------------------------------------------------------------- -- VecList ---------------------------------------------------------------- @@ -508,3 +624,55 @@   {-# INLINE construct #-}   {-# INLINE inspect   #-} instance Arity n => VectorN VecList n a++----------------------------------------------------------------+-- Instances+----------------------------------------------------------------++type instance Dim Complex = N2++instance RealFloat a => Vector Complex a where+  construct = Fun (:+)+  inspect (x :+ y) (Fun f) = f x y+++type instance Dim ((,) a) = N2++instance (b~a) => Vector ((,) b) a where+  construct = Fun (,)+  inspect (a,b) (Fun f) = f a b+++type instance Dim ((,,) a b) = N3++instance (b~a, c~a) => Vector ((,,) b c) a where+  construct = Fun (,,)+  inspect (a,b,c) (Fun f) = f a b c+++type instance Dim ((,,,) a b c) = N4++instance (b~a, c~a, d~a) => Vector ((,,,) b c d) a where+  construct = Fun (,,,)+  inspect (a,b,c,d) (Fun f) = f a b c d+++type instance Dim ((,,,,) a b c d) = N5++instance (b~a, c~a, d~a, e~a) => Vector ((,,,,) b c d e) a where+  construct = Fun (,,,,)+  inspect (a,b,c,d,e) (Fun f) = f a b c d e+++type instance Dim ((,,,,,) a b c d e) = N6++instance (b~a, c~a, d~a, e~a, f~a) => Vector ((,,,,,) b c d e f) a where+  construct = Fun (,,,,,)+  inspect (a,b,c,d,e,f) (Fun fun) = fun a b c d e f+++type instance Dim ((,,,,,,) a b c d e f) = S N6++instance (b~a, c~a, d~a, e~a, f~a, g~a) => Vector ((,,,,,,) b c d e f g) a where+  construct = Fun (,,,,,,)+  inspect (a,b,c,d,e,f,g) (Fun fun) = fun a b c d e f g
Data/Vector/Fixed/Internal.hs view
@@ -1,213 +1,447 @@-{-# LANGUAGE EmptyDataDecls        #-} {-# LANGUAGE TypeFamilies          #-} {-# LANGUAGE Rank2Types            #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE ScopedTypeVariables   #-} -- |--- Type classes for generic vectors. This module exposes type classes--- and auxiliary functions needed to write generic functions not--- present in the module "Data.Vector.Fixed".------ Implementation is based on--- <http://unlines.wordpress.com/2010/11/15/generics-for-small-fixed-size-vectors/>-module Data.Vector.Fixed.Internal (-    -- * Type-level naturals-    Z-  , S-    -- ** Synonyms for small numerals-  , N1-  , N2-  , N3-  , N4-  , N5-  , N6-    -- * N-ary functions-  , Fn-  , Fun(..)-  , Arity(..)-    -- * Vector type class-  , Dim-  , Vector(..)-  , VectorN-  , length-  , Id(..)-  ) where+-- Implementation of fixed-vectors+module Data.Vector.Fixed.Internal where -import Data.Complex-import Prelude hiding (length)+import Data.Vector.Fixed.Internal.Arity+import Data.Vector.Fixed.Cont     (Vector(..),Dim)+import qualified Data.Vector.Fixed.Cont as C +import qualified Prelude as P+import Prelude hiding ( replicate,map,zipWith,maximum,minimum,and,or,all,any+                      , foldl,foldr,foldl1,length,sum+                      , head,tail,mapM,mapM_,sequence,sequence_+                      ) ++ ------------------------------------------------------------------- Naturals+-- Generic functions ---------------------------------------------------------------- --- | Type level zero-data Z--- | Successor of n-data S n+-- TODO: does not fuse! -type N1 = S Z-type N2 = S N1-type N3 = S N2-type N4 = S N3-type N5 = S N4-type N6 = S N5+-- | Generic function for construction of arbitrary vectors. It+--   represents partially constructed vector where /n/ is number of+--   uninitialized elements, /v/ is type of vector and /a/ element type.+--+--   Uninitialized vector could be obtained from 'con' and vector+--   elements could be added from left to right using '|>' operator.+--   Finally it could be converted to vector using 'vec' function.+--+--   Construction of complex number which could be seen as 2-element vector:+--+--   >>> import Data.Complex+--   >>> vec $ con |> 1 |> 3 :: Complex Double+--   1.0 :+ 3.0+newtype New n v a = New (Fn n a (v a)) +-- | Convert fully applied constructor to vector+vec :: New Z v a -> v a+{-# INLINE vec #-}+vec (New v) = v++-- | Seed constructor+con :: Vector v a => New (Dim v) v a+{-# INLINE con #-}+con = f2n construct++-- | Apply another element to vector+(|>) :: New (S n) v a -> a -> New n v a+{-# INLINE  (|>) #-}+New f |> a = New (f a)+infixl 1 |>++f2n :: Fun n a (v a) -> New n v a+{-# INLINE f2n #-}+f2n (Fun f) = New f+++ ------------------------------------------------------------------- N-ary functions++mk1 :: (Vector v a, Dim v ~ C.N1) => a -> v a+mk1 a1 = C.vector $ C.mk1 a1+{-# INLINE mk1 #-}++mk2 :: (Vector v a, Dim v ~ C.N2) => a -> a -> v a+mk2 a1 a2 = C.vector $ C.mk2 a1 a2+{-# INLINE mk2 #-}++mk3 :: (Vector v a, Dim v ~ C.N3) => a -> a -> a -> v a+mk3 a1 a2 a3 = C.vector $ C.mk3 a1 a2 a3+{-# INLINE mk3 #-}++mk4 :: (Vector v a, Dim v ~ C.N4) => a -> a -> a -> a -> v a+mk4 a1 a2 a3 a4 = C.vector $ C.mk4 a1 a2 a3 a4+{-# INLINE mk4 #-}++mk5 :: (Vector v a, Dim v ~ C.N5) => a -> a -> a -> a -> a -> v a+mk5 a1 a2 a3 a4 a5 = C.vector $ C.mk5 a1 a2 a3 a4 a5+{-# INLINE mk5 #-}+++ ---------------------------------------------------------------- --- | Type family for n-ary functions.-type family   Fn n a b-type instance Fn Z     a b = b-type instance Fn (S n) a b = a -> Fn n a b+-- | Replicate value /n/ times.+--+--   Examples:+--+--   >>> import Data.Vector.Fixed.Boxed (Vec2)+--   >>> replicate 1 :: Vec2 Int+--   fromList [1,1]+--+--   >>> replicate 2 :: (Double,Double,Double)+--   (2.0,2.0,2.0)+--+--   >>> import Data.Vector.Fixed.Boxed (Vec)+--   >>> replicate "foo" :: Vec N5 String+--   fromList ["foo","foo","foo","foo","foo"]+replicate :: Vector v a => a -> v a+{-# INLINE replicate #-}+replicate+  = C.vector . C.replicate --- | Newtype wrapper which is used to make 'Fn' injective.-newtype Fun n a b = Fun (Fn n a b) -newtype T_fmap a b n = T_fmap (Fn n a b)+-- | Execute monadic action for every element of vector.+--+--   Examples:+--+--   >>> import Data.Vector.Fixed.Boxed (Vec2,Vec3)+--   >>> replicateM (Just 3) :: Maybe (Vec3 Int)+--   Just fromList [3,3,3]+--   >>> replicateM (putStrLn "Hi!") :: IO (Vec2 ())+--   Hi!+--   Hi!+--   fromList [(),()]+replicateM :: (Vector v a, Monad m) => m a -> m (v a)+{-# INLINE replicateM #-}+replicateM+  = C.vectorM . C.replicateM -instance Arity n => Functor (Fun n a) where-  fmap (f :: b -> c) (Fun g0 :: Fun n a b)-     = Fun $ accum-             (\(T_fmap g) a -> T_fmap (g a))-             (\(T_fmap x) -> f x)-             (T_fmap g0 :: T_fmap a b n)-  {-# INLINE fmap #-} +-- | Unit vector along Nth axis. If index is larger than vector+--   dimensions returns zero vector.+--+--   Examples:+--+--   >>> import Data.Vector.Fixed.Boxed (Vec3)+--   >>> basis 0 :: Vec3 Int+--   fromList [1,0,0]+--   >>> basis 1 :: Vec3 Int+--   fromList [0,1,0]+--   >>> basis 3 :: Vec3 Int+--   fromList [0,0,0]+basis :: (Vector v a, Num a) => Int -> v a+{-# INLINE basis #-}+basis = C.vector . C.basis --- | Type class for handling /n/-ary functions.-class Arity n where-  -- | Left fold over /n/ elements exposed as n-ary function.-  accum :: (forall k. t (S k) -> a -> t k) -- ^ Fold function-        -> (t Z -> b)                      -- ^ Extract result of fold-        -> t n                             -- ^ Initial value-        -> Fn n a b                        -- ^ Reduction function -  -- | Monadic left fold.-  accumM :: Monad m-         => (forall k. t (S k) -> a -> m (t k)) -- ^ Fold function-         -> (t Z -> m b)                        -- ^ Extract result of fold-         -> m (t n)                             -- ^ Initial value-         -> Fn n a (m b)                        -- ^ Reduction function+-- | Unfold vector.+unfoldr :: (Vector v a) => (b -> (a,b)) -> b -> v a+{-# INLINE unfoldr #-}+unfoldr f = C.vector . C.unfoldr f -  -- | Apply all parameters to the function.-  apply :: (forall k. t (S k) -> (a, t k)) -- ^ Get value to apply to function-        -> t n                             -- ^ Initial value-        -> Fn n a b                        -- ^ N-ary function-        -> b -  -- | Monadic apply-  applyM :: Monad m-         => (forall k. t (S k) -> m (a, t k)) -- ^ Get value to apply to function-         -> t n                               -- ^ Initial value-         -> Fn n a (m b)                      -- ^ N-ary function-         -> m b-  -- | Arity of function.-  arity :: n -> Int+-- | Generate vector from function which maps element's index to its+--   value.+--+--   Examples:+--+--   >>> import Data.Vector.Fixed.Unboxed (Vec)+--   >>> generate (^2) :: Vec N4 Int+--   fromList [0,1,4,9]+generate :: (Vector v a) => (Int -> a) -> v a+{-# INLINE generate #-}+generate = C.vector . C.generate -instance Arity Z where-  accum  _ g t = g t-  accumM _ g t = g =<< t-  apply  _ _ h = h-  applyM _ _ h = h-  arity  _ = 0-  {-# INLINE accum  #-}-  {-# INLINE accumM #-}-  {-# INLINE apply  #-}-  {-# INLINE arity  #-} -instance Arity n => Arity (S n) where-  accum  f g t = \a -> accum  f g (f t a)-  accumM f g t = \a -> accumM f g $ flip f a =<< t-  apply  f t h = case f t of (a,u) -> apply f u (h a)-  applyM f t h = do (a,u) <- f t-                    applyM f u (h a)-  arity  n = 1 + arity (prevN n)-    where-      prevN :: S n -> n-      prevN _ = undefined-  {-# INLINE accum  #-}-  {-# INLINE accumM #-}-  {-# INLINE apply  #-}-  {-# INLINE arity  #-}+-- | Generate vector from monadic function which maps element's index+--   to its value.+generateM :: (Monad m, Vector v a) => (Int -> m a) -> m (v a)+{-# INLINE generateM #-}+generateM = C.vectorM . C.generateM    ------------------------------------------------------------------- Type class for vectors----------------------------------------------------------------- --- | Size of vector expressed as type-level natural.-type family Dim (v :: * -> *)+-- | First element of vector.+--+--   Examples:+--+--   >>> import Data.Vector.Fixed.Boxed (Vec3)+--   >>> let x = mk3 1 2 3 :: Vec3 Int+--   >>> head x+--   1+head :: (Vector v a, Dim v ~ S n) => v a -> a+{-# INLINE head #-}+head = C.runContVec C.head . C.cvec --- | Type class for vectors with fixed length.-class Arity (Dim v) => Vector v a where-  -- | N-ary function for creation of vectors.-  construct :: Fun (Dim v) a (v a)-  -- | Deconstruction of vector.-  inspect   :: v a -> Fun (Dim v) a b -> b --- | Vector parametrized by length. In ideal world it should be:+-- | Tail of vector. ----- > forall n. (Arity n, Vector (v n) a, Dim (v n) ~ n) => VectorN v a+--   Examples: ----- Alas polymorphic constraints aren't allowed in haskell.-class (Vector (v n) a, Dim (v n) ~ n) => VectorN v n a+--   >>> import Data.Complex+--   >>> tail (1,2,3) :: Complex Double+--   2.0 :+ 3.0+tail :: (Vector v a, Vector w a, Dim v ~ S (Dim w))+     => v a -> w a+{-# INLINE tail #-}+tail = C.vector . C.tail . C.cvec --- | Length of vector. Function doesn't evaluate its argument.-length :: forall v a. Arity (Dim v) => v a -> Int-{-# INLINE length #-}-length _ = arity (undefined :: Dim v)+-- | Retrieve vector's element at index. Generic implementation is+--   /O(n)/ but more efficient one is used when possible.+(!) :: (Vector v a) => v a -> Int -> a+{-# INLINE (!) #-}+v ! n = runIndex n (C.cvec v) +-- Used in rewriting of index function.+runIndex :: Arity n => Int -> C.ContVec n r -> r+runIndex n = C.runContVec (C.index n)+{-# INLINE[0] runIndex #-} --- | Strict identity monad-newtype Id a = Id { runID :: a }+-- | Left fold over vector+foldl :: Vector v a => (b -> a -> b) -> b -> v a -> b+{-# INLINE foldl #-}+foldl f x = C.runContVec (C.foldl f x)+          . C.cvec -instance Monad Id where-  return     = Id-  Id a >>= f = f a-  {-# INLINE return #-}-  {-# INLINE (>>=)  #-}+-- | Left fold over vector+foldr :: Vector v a => (a -> b -> b) -> b -> v a -> b+{-# INLINE foldr #-}+foldr f x = C.runContVec (C.foldr f x)+          . C.cvec  +-- | Left fold over vector+foldl1 :: (Vector v a, Dim v ~ S n) => (a -> a -> a) -> v a -> a+{-# INLINE foldl1 #-}+foldl1 f = C.runContVec (C.foldl1 f)+         . C.cvec +-- | Left fold over vector+ifoldr :: Vector v a => (Int -> a -> b -> b) -> b -> v a -> b+{-# INLINE ifoldr #-}+ifoldr f x = C.runContVec (C.ifoldr f x)+           . C.cvec++-- | Left fold over vector. Function is applied to each element and+--   its index.+ifoldl :: Vector v a => (b -> Int -> a -> b) -> b -> v a -> b+{-# INLINE ifoldl #-}+ifoldl f z = C.runContVec (C.ifoldl f z)+           . C.cvec++-- | Monadic fold over vector.+foldM :: (Vector v a, Monad m) => (b -> a -> m b) -> b -> v a -> m b+{-# INLINE foldM #-}+foldM f x v = foldl go (return x) v+  where+    go m a = do b <- m+                f b a++-- | Left monadic fold over vector. Function is applied to each element and+--   its index.+ifoldM :: (Vector v a, Monad m) => (b -> Int -> a -> m b) -> b -> v a -> m b+{-# INLINE ifoldM #-}+ifoldM f x v = ifoldl go (return x) v+  where+    go m i a = do { b <- m; f b i a }+++ ------------------------------------------------------------------- Instances++-- | Sum all elements in the vector.+sum :: (Vector v a, Num a) => v a -> a+sum = C.runContVec C.sum . C.cvec+{-# INLINE sum #-}++-- | Maximal element of vector.+--+--   Examples:+--+--   >>> import Data.Vector.Fixed.Boxed (Vec3)+--   >>> let x = mk3 1 2 3 :: Vec3 Int+--   >>> maximum x+--   3+maximum :: (Vector v a, Dim v ~ S n, Ord a) => v a -> a+maximum = C.runContVec C.maximum . C.cvec+{-# INLINE maximum #-}++-- | Minimal element of vector.+--+--   Examples:+--+--   >>> import Data.Vector.Fixed.Boxed (Vec3)+--   >>> let x = mk3 1 2 3 :: Vec3 Int+--   >>> minimum x+--   1+minimum :: (Vector v a, Dim v ~ S n, Ord a) => v a -> a+minimum = C.runContVec C.minimum . C.cvec+{-# INLINE minimum #-}++-- | Conjunction of all elements of a vector.+and :: (Vector v Bool) => v Bool -> Bool+and = C.runContVec C.and . C.cvec+{-# INLINE and #-}++-- | Disjunction of all elements of a vector.+or :: (Vector v Bool) => v Bool -> Bool+or = C.runContVec C.or . C.cvec+{-# INLINE or #-}++-- | Determines whether all elements of vector satisfy predicate.+all :: (Vector v a) => (a -> Bool) -> v a -> Bool+all f = C.runContVec (C.all f) . C.cvec+{-# INLINE all #-}++-- | Determines whether any of element of vector satisfy predicate.+any :: (Vector v a) => (a -> Bool) -> v a -> Bool+any f = C.runContVec (C.any f) . C.cvec+{-# INLINE any #-}++ ---------------------------------------------------------------- -type instance Dim Complex = N2+-- | Test two vectors for equality.+--+--   Examples:+--+--   >>> import Data.Vector.Fixed.Boxed (Vec2)+--   >>> let v0 = basis 0 :: Vec2 Int+--   >>> let v1 = basis 1 :: Vec2 Int+--   >>> v0 `eq` v0+--   True+--   >>> v0 `eq` v1+--   False+eq :: (Vector v a, Eq a) => v a -> v a -> Bool+{-# INLINE eq #-}+eq v w = C.runContVec C.and+       $ C.zipWith (==) (C.cvec v) (C.cvec w) -instance RealFloat a => Vector Complex a where-  construct = Fun (:+)-  inspect (x :+ y) (Fun f) = f x y +---------------------------------------------------------------- -type instance Dim ((,) a) = N2+-- | Map over vector+map :: (Vector v a, Vector v b) => (a -> b) -> v a -> v b+{-# INLINE map #-}+map f = C.vector+      . C.map f+      . C.cvec -instance (b~a) => Vector ((,) b) a where-  construct = Fun (,)-  inspect (a,b) (Fun f) = f a b+-- | Evaluate every action in the vector from left to right.+sequence :: (Vector v a, Vector v (m a), Monad m) => v (m a) -> m (v a)+{-# INLINE sequence #-}+sequence = mapM id +-- | Evaluate every action in the vector from left to right and ignore result+sequence_ :: (Vector v (m a), Monad m) => v (m a) -> m ()+{-# INLINE sequence_ #-}+sequence_ = mapM_ id -type instance Dim ((,,) a b) = N3 -instance (b~a, c~a) => Vector ((,,) b c) a where-  construct = Fun (,,)-  inspect (a,b,c) (Fun f) = f a b c+-- | Monadic map over vector.+mapM :: (Vector v a, Vector v b, Monad m) => (a -> m b) -> v a -> m (v b)+{-# INLINE mapM #-}+mapM f = C.vectorM+       . C.mapM f+       . C.cvec +-- | Apply monadic action to each element of vector and ignore result.+mapM_ :: (Vector v a, Monad m) => (a -> m b) -> v a -> m ()+{-# INLINE mapM_ #-}+mapM_ f = foldl (\m a -> m >> f a >> return ()) (return ()) -type instance Dim ((,,,) a b c) = N4 -instance (b~a, c~a, d~a) => Vector ((,,,) b c d) a where-  construct = Fun (,,,)-  inspect (a,b,c,d) (Fun f) = f a b c d+-- | Apply function to every element of the vector and its index.+imap :: (Vector v a, Vector v b) =>+    (Int -> a -> b) -> v a -> v b+{-# INLINE imap #-}+imap f = C.vector+       . C.imap f+       . C.cvec +-- | Apply monadic function to every element of the vector and its index.+imapM :: (Vector v a, Vector v b, Monad m) =>+    (Int -> a -> m b) -> v a -> m (v b)+{-# INLINE imapM #-}+imapM f = C.vectorM+        . C.imapM f+        . C.cvec -type instance Dim ((,,,,) a b c d) = N5+-- | Apply monadic function to every element of the vector and its+--   index and discard result.+imapM_ :: (Vector v a, Monad m) => (Int -> a -> m b) -> v a -> m ()+{-# INLINE imapM_ #-}+imapM_ f = ifoldl (\m i a -> m >> f i a >> return ()) (return ()) -instance (b~a, c~a, d~a, e~a) => Vector ((,,,,) b c d e) a where-  construct = Fun (,,,,)-  inspect (a,b,c,d,e) (Fun f) = f a b c d e++----------------------------------------------------------------++-- | Zip two vector together using function.+--+--   Examples:+--+--   >>> import Data.Vector.Fixed.Boxed (Vec3)+--   >>> let b0 = basis 0 :: Vec3 Int+--   >>> let b1 = basis 1 :: Vec3 Int+--   >>> let b2 = basis 2 :: Vec3 Int+--   >>> let vplus x y = zipWith (+) x y+--   >>> vplus b0 b1+--   fromList [1,1,0]+--   >>> vplus b0 b2+--   fromList [1,0,1]+--   >>> vplus b1 b2+--   fromList [0,1,1]+zipWith :: (Vector v a, Vector v b, Vector v c)+        => (a -> b -> c) -> v a -> v b -> v c+{-# INLINE zipWith #-}+zipWith f v u = C.vector+              $ C.zipWith f (C.cvec v) (C.cvec u)++-- | Zip two vector together using monadic function.+zipWithM :: (Vector v a, Vector v b, Vector v c, Monad m)+         => (a -> b -> m c) -> v a -> v b -> m (v c)+{-# INLINE zipWithM #-}+zipWithM f v u = C.vectorM+               $ C.zipWithM f (C.cvec v) (C.cvec u)++-- | Zip two vector together using function which takes element index+--   as well.+izipWith :: (Vector v a, Vector v b, Vector v c)+         => (Int -> a -> b -> c) -> v a -> v b -> v c+{-# INLINE izipWith #-}+izipWith f v u = C.vector+               $ C.izipWith f (C.cvec v) (C.cvec u)++-- | Zip two vector together using monadic function which takes element+--   index as well..+izipWithM :: (Vector v a, Vector v b, Vector v c, Monad m)+          => (Int -> a -> b -> m c) -> v a -> v b -> m (v c)+{-# INLINE izipWithM #-}+izipWithM f v u = C.vectorM+                $ C.izipWithM f (C.cvec v) (C.cvec u)+++----------------------------------------------------------------++-- | Convert between different vector types+convert :: (Vector v a, Vector w a, Dim v ~ Dim w) => v a -> w a+{-# INLINE convert #-}+convert = C.vector . C.cvec++-- | Convert vector to the list+toList :: (Vector v a) => v a -> [a]+toList = foldr (:) []++-- | Create vector form list. Will throw error if list is shorter than+--   resulting vector.+fromList :: (Vector v a) => [a] -> v a+{-# INLINE fromList #-}+fromList = C.vector . C.fromList
+ Data/Vector/Fixed/Internal/Arity.hs view
@@ -0,0 +1,119 @@+{-# LANGUAGE EmptyDataDecls        #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE Rank2Types            #-}+{-# LANGUAGE ScopedTypeVariables   #-}+-- |+-- Type class for working with N-ary functions+module Data.Vector.Fixed.Internal.Arity (+    -- * Type-level naturals+    Z+  , S+    -- ** Synonyms for small numerals+  , N1+  , N2+  , N3+  , N4+  , N5+  , N6+    -- * N-ary functions+  , Fn+  , Fun(..)+  , Arity(..)+  ) where++----------------------------------------------------------------+-- Naturals+----------------------------------------------------------------++-- | Type level zero+data Z+-- | Successor of n+data S n++type N1 = S Z+type N2 = S N1+type N3 = S N2+type N4 = S N3+type N5 = S N4+type N6 = S N5++++----------------------------------------------------------------+-- N-ary functions+----------------------------------------------------------------++-- | Type family for n-ary functions.+type family   Fn n a b+type instance Fn Z     a b = b+type instance Fn (S n) a b = a -> Fn n a b++-- | Newtype wrapper which is used to make 'Fn' injective.+newtype Fun n a b = Fun (Fn n a b)++newtype T_fmap a b n = T_fmap (Fn n a b)++instance Arity n => Functor (Fun n a) where+  fmap (f :: b -> c) (Fun g0 :: Fun n a b)+     = Fun $ accum+             (\(T_fmap g) a -> T_fmap (g a))+             (\(T_fmap x) -> f x)+             (T_fmap g0 :: T_fmap a b n)+  {-# INLINE fmap #-}+++-- | Type class for handling /n/-ary functions.+class Arity n where+  -- | Left fold over /n/ elements exposed as n-ary function.+  accum :: (forall k. t (S k) -> a -> t k) -- ^ Fold function+        -> (t Z -> b)                      -- ^ Extract result of fold+        -> t n                             -- ^ Initial value+        -> Fn n a b                        -- ^ Reduction function++  -- | Monadic left fold.+  accumM :: Monad m+         => (forall k. t (S k) -> a -> m (t k)) -- ^ Fold function+         -> (t Z -> m b)                        -- ^ Extract result of fold+         -> m (t n)                             -- ^ Initial value+         -> Fn n a (m b)                        -- ^ Reduction function++  -- | Apply all parameters to the function.+  apply :: (forall k. t (S k) -> (a, t k)) -- ^ Get value to apply to function+        -> t n                             -- ^ Initial value+        -> Fn n a b                        -- ^ N-ary function+        -> b++  -- | Monadic apply+  applyM :: Monad m+         => (forall k. t (S k) -> m (a, t k)) -- ^ Get value to apply to function+         -> t n                               -- ^ Initial value+         -> Fn n a (m b)                      -- ^ N-ary function+         -> m b+  -- | Arity of function.+  arity :: n -> Int++instance Arity Z where+  accum  _ g t = g t+  accumM _ g t = g =<< t+  apply  _ _ h = h+  applyM _ _ h = h+  arity  _ = 0+  {-# INLINE accum  #-}+  {-# INLINE accumM #-}+  {-# INLINE apply  #-}+  {-# INLINE arity  #-}++instance Arity n => Arity (S n) where+  accum  f g t = \a -> accum  f g (f t a)+  accumM f g t = \a -> accumM f g $ flip f a =<< t+  apply  f t h = case f t of (a,u) -> apply f u (h a)+  applyM f t h = do (a,u) <- f t+                    applyM f u (h a)+  arity  n = 1 + arity (prevN n)+    where+      prevN :: S n -> n+      prevN _ = undefined+  {-# INLINE accum  #-}+  {-# INLINE accumM #-}+  {-# INLINE apply  #-}+  {-# INLINE arity  #-}
Data/Vector/Fixed/Mutable.hs view
@@ -29,7 +29,8 @@  import Control.Monad.ST import Control.Monad.Primitive-import Data.Vector.Fixed.Internal+import Data.Vector.Fixed.Internal.Arity+import Data.Vector.Fixed.Cont (Dim) import Prelude hiding (read)  
Data/Vector/Fixed/Primitive.hs view
@@ -13,6 +13,8 @@   , Vec3     -- * Mutable   , MVec+    -- * Type classes+  , Prim   ) where  import Control.Monad@@ -21,7 +23,7 @@ import Prelude hiding (length,replicate,zipWith,map,foldl)  import Data.Vector.Fixed-import Data.Vector.Fixed.Internal+import Data.Vector.Fixed.Internal.Arity import Data.Vector.Fixed.Mutable  @@ -82,10 +84,12 @@ type instance DimM (MVec n) = n  instance (Arity n, Prim a) => Vector (Vec n) a where-  construct = constructVec-  inspect   = inspectVec-  {-# INLINE construct #-}-  {-# INLINE inspect   #-}+  construct  = constructVec+  inspect    = inspectVec+  basicIndex = index+  {-# INLINE construct  #-}+  {-# INLINE inspect    #-}+  {-# INLINE basicIndex #-} instance (Arity n, Prim a) => VectorN Vec n a  instance (Arity n, Prim a, Eq a) => Eq (Vec n a) where
Data/Vector/Fixed/Storable.hs view
@@ -15,6 +15,8 @@   , unsafeWith     -- * Mutable   , MVec(..)+    -- * Type classes+  , Storable   ) where  import Control.Monad.Primitive@@ -27,7 +29,7 @@ import Prelude hiding (length,replicate,zipWith,map,foldl)  import Data.Vector.Fixed-import Data.Vector.Fixed.Internal+import Data.Vector.Fixed.Internal.Arity import Data.Vector.Fixed.Mutable  @@ -128,10 +130,12 @@ type instance DimM (MVec n) = n  instance (Arity n, Storable a) => Vector (Vec n) a where-  construct = constructVec-  inspect   = inspectVec-  {-# INLINE construct #-}-  {-# INLINE inspect   #-}+  construct  = constructVec+  inspect    = inspectVec+  basicIndex = index+  {-# INLINE construct  #-}+  {-# INLINE inspect    #-}+  {-# INLINE basicIndex #-} instance (Arity n, Storable a) => VectorN Vec n a  instance (Arity n, Storable a, Eq a) => Eq (Vec n a) where
Data/Vector/Fixed/Unboxed.hs view
@@ -24,7 +24,7 @@ import Data.Word (Word,Word8,Word16,Word32,Word64) import Prelude hiding (length,replicate,zipWith,map,foldl) -import Data.Vector.Fixed+import Data.Vector.Fixed (Dim,Arity,Vector(..),VectorN,S,Z,toList,eq) import Data.Vector.Fixed.Mutable import qualified Data.Vector.Fixed.Primitive as P @@ -55,10 +55,14 @@ type instance DimM (MVec n) = n  instance (Unbox n a) => Vector (Vec n) a where-  construct = constructVec-  inspect   = inspectVec-  {-# INLINE construct #-}-  {-# INLINE inspect   #-}+  construct  = constructVec+  inspect    = inspectVec+  basicIndex = index+  {-# INLINE construct  #-}+  {-# INLINE inspect    #-}+  {-# INLINE basicIndex #-}++ instance (Unbox n a) => VectorN Vec n a  instance (Unbox n a, Eq a) => Eq (Vec n a) where
fixed-vector.cabal view
@@ -1,18 +1,34 @@ Name:           fixed-vector-Version:        0.2.0.0-Synopsis:       Generic vectors with fixed length+Version:        0.3.0.0+Synopsis:       Generic vectors with statically known size. Description:-  Generic vectors with fixed length. Package is structured as follows:+  Generic library for vectors with statically known+  size. Implementation is based on+  <http://unlines.wordpress.com/2010/11/15/generics-for-small-fixed-size-vectors/>+  Same functions could be used to work with both ADT based vector like   .+  > data Vec3 a = a a a+  .+  Tuples are vectors too:+  .+  >>> sum (1,2,3)+  6+  .+  Vectors which are represented internally by arrays are provided by+  library. Both boxed and unboxed arrays are supported.+  .+  Library is structured as follows:+  .   [@Data.Vector.Fixed@]   Generic API. It's suitable for both ADT-based vector like @Complex@   and array-based ones.   .   [@Data.Vector.Fixed.Cont@]-  Continuation based vectors.+  Continuation based vectors. Internally all functions use them.   .   [@Data.Vector.Fixed.Mutable@]-  Type classes for array-based implementation.+  Type classes for array-based implementation and API for working with+  mutable state.   .   [@Data.Vector.Fixed.Unboxed@]   Unboxed vectors.@@ -26,6 +42,14 @@   [@Data.Vector.Fixed.Primitive@]   Unboxed vectors based on pritimive package.   .+  Changes in 0.3.0.0+  .+  * @Vector@ type class definition is moved to the @D.V.F.Cont@ module.+  .+  * Indexing function restored.+  .+  * @unfoldr@ added.+  .   Changes in 0.2.0.0   .   * Continuation-based vector added.@@ -73,15 +97,17 @@     primitive   Exposed-modules:     -- API-    Data.Vector.Fixed-    Data.Vector.Fixed.Internal+    Data.Vector.Fixed.Internal.Arity     Data.Vector.Fixed.Cont-    Data.Vector.Fixed.Mutable+    Data.Vector.Fixed     -- Arrays+    Data.Vector.Fixed.Mutable     Data.Vector.Fixed.Boxed     Data.Vector.Fixed.Primitive     Data.Vector.Fixed.Unboxed     Data.Vector.Fixed.Storable+  Other-modules:+    Data.Vector.Fixed.Internal  Test-Suite doctests   Type:           exitcode-stdio-1.0