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 +24/−425
- Data/Vector/Fixed/Boxed.hs +7/−5
- Data/Vector/Fixed/Cont.hs +177/−9
- Data/Vector/Fixed/Internal.hs +390/−156
- Data/Vector/Fixed/Internal/Arity.hs +119/−0
- Data/Vector/Fixed/Mutable.hs +2/−1
- Data/Vector/Fixed/Primitive.hs +9/−5
- Data/Vector/Fixed/Storable.hs +9/−5
- Data/Vector/Fixed/Unboxed.hs +9/−5
- fixed-vector.cabal +34/−8
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