我开始玩Haskell,阅读一些教程和一本官方书籍(lyah)。我觉得自己能够开始我的第一个个人项目。至于我选择的任何新语言,我想实现一个用于线性代数处理的包(围绕矩阵,向量等的操作)。功能还可以,但我对数据类型没有太多的了解。
最初,我有一个看起来像这样的功能:
add_vect :: (Num a) => [a] -> [a] -> [a]
add_vect x y = zipWith (+) x y
现在我想给Vector
的含义命名([a]
),以便vect_add
看起来像:
vect_add :: Vector -> Vector -> Vector
vect_add x y = zipWith (+) x y
经过多次雄心勃勃的尝试后,我以一个非常简单的定义结束了(受String
定义的启发):
type Vector = [Int]
这个问题是我失去了我的函数的类型泛型,它现在仅适用于[Int]
而不是任何数字类型。
我的问题是:有没有办法在新类型的定义中表达通用性(例如使用类型calsses)。类似于:
type Vector = (Num a) => [a]
或者是否有其他方法可以保持Vector
的通用性?
答案 0 :(得分:3)
你无法做你想做的事,因为类型检查器无法知道所有三个向量都是相同的类型。否则你可以写这样的代码:
mkVect :: [a] -> Vector -- You are going to need something with this type.
x1 :: [Int]
x1 = [1,2,3]
x2 :: [Double]
x2 = [1.0,2.0,3.0]
v3 = add_vect (mkVect x1) (mkVect x2)
类型检查器可以阻止这种情况的唯一方法是将Vector的type参数作为add_vect的一部分。
所以你必须写
type Vector a = [a]
通过这种方式,类型检查器可以看到你在做什么。
答案 1 :(得分:3)
嗯...
{-# LANGUAGE RankNTypes #-}
type Vector = forall a . Num a => [a]
但那并不是你想要的:你最终得到了
addVect :: (forall a.Num a => [a]) -> (forall b.Num b => [b]) -> (forall c.Num c => [c])
无法定义(每个向量可能有不同的数字类型)。
正如保罗约翰逊所说,你可以使用type Vector a = [a]
(或等同地,type Vector = []
)。但我不认为这真的是你想要的:你基本上会得到与现在相同的签名,并且在跨越矢量空间的场上具有参数多态的矢量函数并不是很自然。
正确的解决方案IMO是vector-space
package :(简化)
class VectorSpace v where
type Scalar v :: * -- This is going to be the type of the
-- field ("of the components of each vector")
(^+^) :: v -> v -> v -- You call this `addVect`
(*^) :: (Scalar v) -> v -> v
...
然后你可以有例如。
data Vectorℝ2 = Vectorℝ2 !Double !Double
instance VectorSpace Vectorℝ2 where
type Scalar Vectorℝ2 = Double
Vectorℝ2 x y ^+^ Vectorℝ2 x' y' = Vectorℝ2 (x+x') (y+y')
...
或
newtype Vectorℝn = Vectorℝn [Double]
instance VectorSpace Vectorℝn where
type Scalar Vectorℝn = Double
Vectorℝn xs ^+^ Vectorℝn x's = Vectorℝn $ zipWith (+) xs x's
BTW,zipWith(+)
对于变量维向量加法来说并不是一个很好的定义:你会得到例如。
[1,2,3] ^+^ [4,5] ≡ [5,7]
虽然实际上我希望在矢量意义上[4,5] ≅ [4,5,0]
,因此[1,2,3] ^+^ [4,5] ≡ [5,7,3] ≆ [5,7]
。
答案 2 :(得分:0)
一种“正确”的方式是注意您仅使用Vector
进行文档编制,因此type Vector a = [a]
并不是一件坏事。然后,您必须vect_add :: Vector a -> Vector a -> Vector a
必须匹配,甚至vector-space
的{{1}}。