2013-07-26 59 views
2

我已經開始使用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

即使你可以做你想做的事情,因爲'a'不是一個具體類型,你仍然不得不將'Vector'變成一個**類型的構造函數**'Vector a' ..就像你不能擁有'Maybe = Nothing |只是一個'。 'Maybe'是一個類型構造函數,'Maybe Int'是一個類型。 –

回答

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) 

類型檢查可以停止,這是由具有矢量類型參數爲add_vect的一部分的唯一途徑。

因此,你必須寫

type Vector a = [a] 

這樣類型檢查可以看到你在做什麼。

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]) 

不能定義(每個向量可以有不同的數字類型)。

正如Paul Johnson所說,您可以使用使用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]

+0

我必須經歷所有這些。練習這些特定的語言特定的東西。非常感謝您的回覆。 PS:我沒有在我的代碼版本中使用zipWith – mbelaoucha

0

一個「正確」的方法是隻注意到你只使用Vector作爲文檔目的,所以type Vector a = [a]不是壞事。然後你有vect_add :: Vector a -> Vector a -> Vector a必須匹配,甚至vector-space(*^) :: a -> Vector a -> Vector a

相關問題