我试图在Haskell中实现无限维向量空间,但我遇到了麻烦。我将使用流作为基本数据类型,并简单地使用为向量空间提供的包,但我希望索引在负方向和正方向上都有。换句话说,我需要从整数(所有整数)到标量值的某种映射。这很容易实现,例如
(^+^) :: (Integer -> Double) -> (Integer -> Double) -> (Integer -> Double)
a ^+^ b = ( n -> (a n) + (b n))
(^*^) :: Double -> (Integer -> Double) -> (Integer -> Double)
c ^*^ a = ( n -> c * (a n))
和
一样使用vecA :: (Integer -> Double)
vecB :: (Integer -> Double)
vecA n = fromInteger n
vecB n = fromInteger n
print ((vecA ^+^ vecB) 4) --prints 8.0, as expected
好的,我想让它更通用,naïvely,我想这样写,
class AdditiveGroup v where
-- | The zero element: identity for '(^+^)'
zeroV :: v
-- | Add vectors
(^+^) :: v -> v -> v
-- | Additive inverse
negateV :: v -> v
-- | Group subtraction
(^-^) :: v -> v -> v
v ^-^ v' = v ^+^ negateV v'
class AdditiveGroup v => VectorSpace v where
type Scalar v :: *
-- | Scale a vector
(*^) :: Scalar v -> v -> v
(我从Haskell的类中复制并粘贴了这个定义。)但是,当然,没有一种方法(我可以看到)将我上面的映射实现为数据结构,并且试图改变v的类型会使我遇到问题
--This doesn't even compile
class InfVecSpace v where
type Index v :: *
type Scalar v :: *
type Member v :: * -> *
(^+^) :: (Member v) -> (Member v) -> (Member v)
zeroV :: (Member v)
invertV :: (Member v) -> (Member v)
(^*^) :: Scalar v -> (Member v) -> (Member v)
我如何在Haskell的类型系统中实现这一点,最好是尽可能地符合习惯?
绝对没有必要创建一个新类;相反,只需为函数类型创建旧类的实例。例如:
instance AdditiveGroup v => AdditiveGroup (e -> v) where
zeroV _ = zeroV
(f ^+^ g) x = f x ^+^ g x
negateV f x = negateV (f x)
instance VectorSpace v => VectorSpace (e -> v) where
type Scalar (e -> v) = Scalar v
(a *^ f) x = a *^ f x