我有一个数学向量的自定义类型
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
class Vector v a where
infixl 6 <+>
(<+>) :: v -> v -> v -- vector addition
infixl 6 <->
(<->) :: v -> v -> v -- vector subtraction
infixl 7 *>
(*>) :: a -> v -> v -- multiplication by a scalar
dot :: v -> v -> a -- inner product
我希望将数字a
和函数a -> vector
放入类的实例中。数字很简单:
instance Num a => Vector a a where
(<+>) = (+)
(<->) = (-)
(*>) = (*)
dot = (*)
我认为功能也很简单(好吧,dot
除外,但我可以忍受)
instance Vector b c => Vector (a -> b) c where
f <+> g = \a -> f a <+> g a
f <-> g = \a -> f a <-> g a
c *> f = \a -> c *> f a
dot = undefined
但是,我收到以下错误:
Ambiguous type variable `a0' in the constraint:
(Vector b a0) arising from a use of `<+>'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: f a <+> g a
In the expression: \ a -> f a <+> g a
In an equation for `<+>': f <+> g = \ a -> f a <+> g a
如何告诉GHC该实例对所有类型a
有效?我应该在哪里添加类型签名?
答案 0 :(得分:5)
类型系列绝对是解决此问题最可靠的方法
{-# LANGUAGE TypeFamilies, FlexibleContexts #-}
class VectorSpace v where
type Field v
infixl 6 <+>
(<+>) :: v -> v -> v -- vector addition
infixl 6 <->
(<->) :: v -> v -> v -- vector subtraction
infixl 7 *>
(*>) :: Field v -> v -> v -- multiplication by a scalar
dot :: v -> v -> Field v -- inner product
在数学上,要从函数中创建向量空间,必须重用相同的字段:
instance VectorSpace b => VectorSpace (a -> b) where
type Field (a -> b) = Field b
f <+> g = \a -> f a <+> g a
f <-> g = \a -> f a <-> g a
c *> f = \a -> c *> f a
dot = error "Can't define the dot product on functions, sorry."
...关于类型系列的好处是它们非常适合你解释的方式。 让我们做两个向量空间的直接乘积:
instance (VectorSpace v,VectorSpace w, Field v ~ Field w,Num (Field v)) => VectorSpace (v,w) where
type Field (v,w) = Field v
(v,w) <+> (v',w') = (v <+> v',w <+> w')
(v,w) <-> (v',w') = (v <-> v',w <-> w')
c *> (v,w) = (c *> v, c*> w)
(v,w) `dot` (v',w') = (v `dot` v') + (w `dot` w')
您可以使用自定义代数类替换Num
上下文,但Num
会捕获概念
田野适度。
答案 1 :(得分:2)
我能够制作以下小例子(在Conal Elliott的vector-space包之后编译)编译:
{-# LANGUAGE TypeFamilies #-}
module Main
where
class Vector v where
type Scalar v
infixl 6 <+>
(<+>) :: v -> v -> v -- vector addition
infixl 7 *>
(*>) :: (Scalar v) -> v -> v -- multiplication by a scalar
instance Vector v => Vector (a -> v) where
type Scalar (a -> v) = (a -> Scalar v)
f <+> g = \a -> f a <+> g a
(*>) c f = \a -> c a *> f a -- Can't deduce that Scalar v ~ Scalar (a -> v)
有可能使用函数依赖而不是类型族来完成这项工作。