vector-space-map 0.1.0.1 → 0.2.0
raw patch · 3 files changed
+45/−33 lines, 3 filesdep +doctestdep ~basedep ~vector-spacePVP ok
version bump matches the API change (PVP)
Dependencies added: doctest
Dependency ranges changed: base, vector-space
API changes (from Hackage documentation)
- Data.Map.Vector: instance (AdditiveGroup v, Ord k) => AdditiveGroup (MapVector k v)
- Data.Map.Vector: instance (Data k, Data v, Ord k) => Data (MapVector k v)
- Data.Map.Vector: instance (Eq k, Eq v) => Eq (MapVector k v)
- Data.Map.Vector: instance (Ord k, AdditiveGroup v, Num v) => Num (MapVector k v)
- Data.Map.Vector: instance (Ord k, Read k, Read v) => Read (MapVector k v)
- Data.Map.Vector: instance (Ord k, VectorSpace v) => VectorSpace (MapVector k v)
- Data.Map.Vector: instance (Ord k, VectorSpace v, InnerSpace v, AdditiveGroup (Scalar v)) => InnerSpace (MapVector k v)
- Data.Map.Vector: instance (Show k, Show v) => Show (MapVector k v)
- Data.Map.Vector: instance Foldable (MapVector k)
- Data.Map.Vector: instance Functor (MapVector k)
- Data.Map.Vector: instance Ord k => Applicative (MapVector k)
- Data.Map.Vector: instance Traversable (MapVector k)
- Data.Map.Vector: instance Typeable2 MapVector
+ Data.Map.Vector: instance (Data.AdditiveGroup.AdditiveGroup v, GHC.Classes.Ord k) => Data.AdditiveGroup.AdditiveGroup (Data.Map.Vector.MapVector k v)
+ Data.Map.Vector: instance (Data.Data.Data k, Data.Data.Data v, GHC.Classes.Ord k) => Data.Data.Data (Data.Map.Vector.MapVector k v)
+ Data.Map.Vector: instance (GHC.Classes.Eq k, GHC.Classes.Eq v) => GHC.Classes.Eq (Data.Map.Vector.MapVector k v)
+ Data.Map.Vector: instance (GHC.Classes.Ord k, Data.Basis.HasBasis v, Data.AdditiveGroup.AdditiveGroup (Data.VectorSpace.Scalar v)) => Data.Basis.HasBasis (Data.Map.Vector.MapVector k v)
+ Data.Map.Vector: instance (GHC.Classes.Ord k, Data.VectorSpace.VectorSpace v) => Data.VectorSpace.VectorSpace (Data.Map.Vector.MapVector k v)
+ Data.Map.Vector: instance (GHC.Classes.Ord k, Data.VectorSpace.VectorSpace v, Data.VectorSpace.InnerSpace v, Data.AdditiveGroup.AdditiveGroup (Data.VectorSpace.Scalar v)) => Data.VectorSpace.InnerSpace (Data.Map.Vector.MapVector k v)
+ Data.Map.Vector: instance (GHC.Classes.Ord k, GHC.Base.Monoid v) => GHC.Base.Monoid (Data.Map.Vector.MapVector k v)
+ Data.Map.Vector: instance (GHC.Classes.Ord k, GHC.Read.Read k, GHC.Read.Read v) => GHC.Read.Read (Data.Map.Vector.MapVector k v)
+ Data.Map.Vector: instance (GHC.Show.Show k, GHC.Show.Show v) => GHC.Show.Show (Data.Map.Vector.MapVector k v)
+ Data.Map.Vector: instance Data.Foldable.Foldable (Data.Map.Vector.MapVector k)
+ Data.Map.Vector: instance Data.Traversable.Traversable (Data.Map.Vector.MapVector k)
+ Data.Map.Vector: instance GHC.Base.Functor (Data.Map.Vector.MapVector k)
+ Data.Map.Vector: instance GHC.Classes.Ord k => GHC.Base.Applicative (Data.Map.Vector.MapVector k)
Files
- doctests.hs +2/−0
- src/Data/Map/Vector.hs +32/−27
- vector-space-map.cabal +11/−6
+ doctests.hs view
@@ -0,0 +1,2 @@+import Test.DocTest +main = doctest ["-isrc", "src/Data/Map/Vector.hs"]
src/Data/Map/Vector.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE TypeFamilies, FlexibleContexts #-} {-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable, DeriveDataTypeable #-} +{-# LANGUAGE TupleSections #-} module Data.Map.Vector (MapVector(..)) where import Prelude hiding (foldr) @@ -7,8 +8,10 @@ import Data.Traversable import Data.Data import Control.Applicative +import Control.Arrow import Data.AdditiveGroup import Data.VectorSpace +import Data.Basis import Data.Map (Map) import qualified Data.Map as Map @@ -17,16 +20,15 @@ -- | Note: '<*>' in the 'Applicative' instance operates under /intersection/. i.e.: -- -- >>> (MapVector $ Map.fromList [("x", id)]) <*> (MapVector $ Map.fromList [("y", 3)]) --- MapVector (Map.fromList []) +-- MapVector (fromList []) -- --- '*' in the 'Num' instance performs elementwise multiplication. It is defined in terms of --- '<*>' and therefore also operates under intersection: +-- Use the 'Applicative' instance for elementwise operations: -- --- >>> (MapVector $ Map.fromList [("x", 2), ("y", 3)]) * (MapVector $ Map.fromList [("x", 5),("y", 7)]) --- MapVector (Map.fromList [("x", 10), ("y", 21)]) +-- >>> liftA2 (*) (MapVector $ Map.fromList [("x", 2), ("y", 3)]) (MapVector $ Map.fromList [("x", 5),("y", 7)]) +-- MapVector (fromList [("x",10),("y",21)]) -- --- >>> (MapVector $ Map.fromList [("x", 2), ("y", 3)]) * (MapVector $ Map.fromList [("y", 7)]) --- MapVector (Map.fromList [("y", 21)]) +-- >>> liftA2 (*) (MapVector $ Map.fromList [("x", 2), ("y", 3)]) (MapVector $ Map.fromList [("y", 7)]) +-- MapVector (fromList [("y",21)]) -- -- '*^' in the 'VectorSpace' instance multiplies by the scalar of v. Nesting MapVectors preserves -- the scalar type, e.g. @Scalar (MapVector k (MapVector k' v))@ = @Scalar v@. @@ -42,13 +44,18 @@ -- >>> (pure . MapVector $ Map.fromList [("x", 2 :: Int), ("y", 3)]) <.> (MapVector $ Map.fromList [("a", pure (5::Int))]) -- 25 -- --- Addition, using either '+' or '^+^', operates under union. +-- Addition with '^+^' operates under union. data MapVector k v = MapVector (Map k v) | ConstantMap v -- ^ An infinite-dimensional vector with the same value on all dimensions deriving (Eq, Functor, Show, Read, Foldable, Traversable, Typeable, Data) +-- | Respects the inner 'Monoid', unlike 'Map'. +instance (Ord k, Monoid v) => Monoid (MapVector k v) where + mempty = pure mempty + mappend = liftA2 mappend + instance (Ord k) => Applicative (MapVector k) where pure = ConstantMap (ConstantMap f) <*> (ConstantMap v) = ConstantMap $ f v @@ -79,24 +86,22 @@ (MapVector vs) <.> (MapVector vs') = foldl' (^+^) zeroV $ Map.intersectionWith (<.>) vs vs' {-# INLINABLE (<.>) #-} -instance (Ord k, AdditiveGroup v, Num v) => Num (MapVector k v) where - (+) = (^+^) - {-# INLINE (+) #-} - x * y = (*) <$> x <*> y - {-# INLINE (*) #-} - abs = fmap abs - {-# INLINE abs #-} - fromInteger = pure . fromInteger - signum = error "no signum for MapVectors" - --- It looks like a HasBasis instance should be possible; --- I just haven't spent the time to figure it out. +instance (Ord k, HasBasis v, AdditiveGroup (Scalar v)) => HasBasis (MapVector k v) where + type Basis (MapVector k v) = (k, Basis v) --- (Remember to tighten version bounds on vector-space if this is implemented.) + basisValue (k, v) = MapVector $ Map.fromList $ (k, basisValue v):[] + + decompose (MapVector vs) + = Map.toList (decompose<$>vs) >>= \(k,vs) -> first(k,)<$>vs + decompose (ConstantMap _) = error "decompose: not defined for ConstantMap.\ + \ Use decompose', which works properly on infinite-dimensional spaces." + -- Note that it would be possible to properly implement 'decompose' under + -- the additional constraint that the keys are enumerable. See e.g. the + -- @universe-base@ package. ---instance (Ord k, HasBasis v) => HasBasis (MapVector k v) where --- type Basis (MapVector k v) = (k, Basis v) --- basisValue (k, v) = MapVector $ Map.fromList $ (k, basisValue v):[] --- --- decompose (ConstantMap _) = error "decompose: not defined for ConstantMap" --- decompose (MapVector vs) = + decompose' (MapVector vs) (k,bv) = case Map.lookup k vs of + Nothing -> zeroV + Just v -> decompose' v bv + decompose' (ConstantMap c) (_,bv) = decompose' c bv + +
vector-space-map.cabal view
@@ -2,9 +2,9 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: vector-space-map -version: 0.1.0.1 +version: 0.2.0 synopsis: vector-space operations for finite maps using Data.Map -description: Data.Map.Vector provides @MapVector@, a wrapper around @Map@ from @containers@ which supports constant maps, i.e. maps containing only one value. This allows an identity under intersection and an @Applicative@ instance. It also has instances of @AdditiveGroup@, @VectorSpace@, @InnerSpace@, and @Num@ with appropriate value types. Provides operations for addition, subtraction, element-wise multiplication (through @Num@), scalar multiplication (through @VectorSpace@), and dot product. +description: Data.Map.Vector provides @MapVector@, a wrapper around @Map@ from @containers@ which supports constant maps, i.e. maps containing only one value. This allows an identity under intersection and an @Applicative@ instance. It also has instances of @AdditiveGroup@, @VectorSpace@, @InnerSpace@, and @HasBasis@ with appropriate value types. Provides operations for addition, subtraction, element-wise operations (through @Applicative@), scalar multiplication (through @VectorSpace@), and dot product. Also consider Conal Elliott's @total-map@ package. homepage: https://github.com/conklech/vector-space-map license: MIT license-file: LICENSE @@ -13,7 +13,7 @@ category: Math build-type: Simple -cabal-version: >=1.6 +cabal-version: >=1.8 source-repository head type: git @@ -22,10 +22,15 @@ source-repository this type: git location: git://github.com/conklech/vector-space-map.git - tag: 0.1.0.1 + tag: 0.2.0 library hs-source-dirs: src exposed-modules: Data.Map.Vector - build-depends: base < 5, containers < 0.6, vector-space < 0.9 - + build-depends: base < 5, containers < 0.6, vector-space >= 0.5 && < 0.11 + +test-suite doctests + type: exitcode-stdio-1.0 + ghc-options: -threaded + main-is: doctests.hs + build-depends: base, doctest >= 0.8