我想定义几个版本的东西,但是使用不同的类型来增强程序中的类型安全性。例如,我有几种类型的双变量值,我希望它们是Num
的实例,但都应该是不同的类型。所以我所做的是创建一个带有一个类型变量的newtype并根据它声明新类型。但是,我觉得有点烦人,我现在必须一直使用两个构造函数。有没有办法解决?
{-# 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
也可以吗?
答案 0 :(得分:2)
为什么不将所有作为新类型,甚至是Bivar
?
instance (Num a, Num b) => Num (a, b) where
(a, b) + (a', b') = (a+a', b+b')
(a, b) * (a', b') = (a*a', b*b')
(a, b) - (a', b') = (a-a', b-b')
fromInteger i = (fromInteger i, fromInteger i)
abs (a, b) = (abs a, abs b)
signum (a, b) = (signum a, signum b)
newtype Bivar t = Bivar (t , t ) deriving (Show, Eq, Num)
newtype BivarNode = BivarNode (Int , Int ) deriving (Show, Eq, Num)
newtype BivarVal = BivarVal (Double, Double) deriving (Show, Eq, Num)
newtype HBivarVal = HBivarVal (Double, Double) deriving (Show, Eq, Num)
答案 1 :(得分:1)
是的,您可以定义辅助函数:
bivarVal = BivarVal . Bivar
hBivarVal = HBivarVal . Bivar
bivarNode = BivarNode . Bivar