langs/Haskell/lin-alg/Vector.hs

87 lines
3.0 KiB
Haskell

-- (C) Copyright Collin Doering 2014
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- File: Vector.hs
-- Author: Collin J. Doering <rekahsoft@gmail.com>
-- Date: Feb 5, 2014
-- Inspired by Coursera class "Coding the Matrix"
-- | This Module represents Vectors
module Vector where
import Data.Foldable
import qualified Data.Map.Strict as M
import Data.Maybe (fromMaybe,fromJust)
-- | Vector
data Vector a = Vector { unvector :: M.Map Integer a }
instance Show a => Show (Vector a) where
show (Vector a) = "Vector " ++ M.foldr (\x y -> show x ++ " " ++ y) "" a
instance Functor Vector where
fmap f (Vector v) = Vector $ M.map f v
instance Foldable Vector where
foldr f i (Vector v) = M.foldr f i v
-- class Field a => Vector a where
-- (+) = udnefined
-- (-) = undefined
-- (*) = undefined
-- The Num class doesn't exactly fit for Vectors
-- instance Num a => Num (Vector a) where
-- (+) = addVector
-- (-) = subVector
-- (*) = scalarMultVector
-- negate v = fmap (*(-1)) v
-- abs v = undefined
-- fromInteger a = fromList [a]
-- | Returns the dimension of the given Vector
dimension :: Num a => Vector a -> Integer
dimension (Vector v) = toInteger . M.size $ v
-- | Given a list, returns it represented as a Vector
fromList :: Num a => [a] -> Vector a
fromList xs = Vector $ M.fromList $ zip [1..] xs
-- |
scalarMultVector :: Num a => a -> Vector a -> Vector a
scalarMultVector a (Vector v) = Vector $ M.map (a*) v
-- |
binOpVector :: Num a => (Int -> Int -> Bool) -> String -> (a -> a -> a) -> Vector a -> Vector a -> Vector a
binOpVector p e f (Vector v1) (Vector v2)
| p (M.size v1) (M.size v2) = Vector $ M.foldrWithKey (\k x y -> M.insert k (f x (fromMaybe (error "Internal error!") $ M.lookup k v2)) y) M.empty v1
| otherwise = error e
-- | Add two given Vectors
addVector :: Num a => Vector a -> Vector a -> Vector a
addVector = binOpVector (==) "Error! Can only add vectors of the same dimension." (+)
-- | Subtract two given Vectors
subVector :: Num a => Vector a -> Vector a -> Vector a
subVector = binOpVector (==) "Error! Can only subtract vectors of the same dimension." (-)
-- | Apply the dot product to two given vectors
dotVector :: Num a => Vector a -> Vector a -> a
dotVector x@(Vector v1) y@(Vector v2) = M.foldr (+) 0 $ unvector $ binOpVector (==) "Error! Can only perform dot product on Vectors of equal size." (*) x y
(<.>) :: Num a => Vector a -> Vector a -> a
(<.>) = dotVector