我想定義一個事物的幾個版本,但是使用不同的類型來增強我的程序中的類型安全性。例如,我有幾種類型的雙變量值,我想要成爲Num
的實例,但所有變量都應該是不同的類型。所以我所做的就是用一個類型變量創建一個新類型並基於此類型聲明新類型。然而,我覺得現在不得不一直使用這兩個構造函數,這有點令人討厭。有沒有辦法解決?Haskell:類型安全同義詞的新類型:使用兩個構造函數的任何方式?
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Bivar t = Bivar (t,t) deriving (Show, Eq)
instance (Num t) => Num (Bivar t) where
(+) (Bivar (x1,y1)) (Bivar (x2,y2)) = Bivar (x1+x2, y1+y2)
(-) (Bivar (x1,y1)) (Bivar (x2,y2)) = Bivar (x1-x2, y1-y2)
(*) (Bivar (x1,y1)) (Bivar (x2,y2)) = Bivar (x1*x2, y1*y2)
abs (Bivar (x1,y1)) = Bivar (abs x1, abs y1)
fromInteger i = Bivar (fromInteger i, fromInteger i)
signum (Bivar (x1,y1)) = Bivar (signum x1, signum y1)
newtype BivarNode = BivarNode (Bivar Int) deriving (Show, Eq, Num)
newtype BivarVal = BivarVal (Bivar Double) deriving (Show, Eq, Num)
newtype HBivarVal = HBivarVal (Bivar Double) deriving (Show, Eq, Num)
-- This is annoying:
a1 = BivarVal (Bivar (1.0, 2.0))
a2 = HBivarVal (Bivar (1.0, 2.0))
b = BivarNode (Bivar (1,2))
-- is there a way so that I can write it this way?
aa1 = BivarVal (1.0, 2.0)
aa2 = HBivarVal (1.0, 2.0)
bb = BivarNode (1,2)
謝謝!
編輯:
要在原來的問題擴大,我也想對模式匹配,沿
myFunction :: HBivarVal -> Double
myFunction (HBivarVal (Bivar (x,y))) = x
線的東西所用的類型名稱是可能的嗎?
對於第二個問題:使用視圖模式。 – 2012-04-28 12:59:08
@ ThomasM.DuBuisson謝謝你,請檢查一下 – Paul 2012-04-28 16:50:44
Newtype包裝一對並沒有給你帶來什麼好處(雖然GHC會優化掉新包裝,但所有的模式匹配都必須使用這兩個包),所以數據Bivar t = Bivar tt'是等效的,並且按鍵次數略少... – 2012-04-28 17:55:41