2015-02-23 85 views
2

我正在开发一套Haskell中的一小块举重实用程序作为学习练习。我定义的数据类型Weight使得:Haskell自定义数据类型,实例编号和冗余

data Weight = Wt Float Unit 
       deriving (Show, Eq) 

data Unit = Lb | Kg 
       deriving (Show, Eq) 

instance Num Weight where 
    Wt x Lb + Wt y Lb = Wt (x + y) Lb 
    Wt x Lb * Wt y Lb = Wt (x * y) Lb 
    negate (Wt x Lb) = Wt (negate x) Lb 
    abs (Wt x Lb) = Wt (abs x) Lb 
    signum (Wt x Lb) = Wt (signum x) Lb 
    fromInteger x  = Wt (fromInteger x) Lb 
    -- Repeat for Kg... 

有没有什么办法可以指定一个泛型类型在民实例定义的Unit?这将是很好的指定类似的东西:

instance Num Weight where 
    Wt x a + Wt y a = Wt (x + y) a 
    -- ... 

而不是重复所有与其他构造函数。

+2

小心!千克是质量单位,而不是重量。 SI(派生)单位重量是牛顿,等于1公斤米/秒^ 2。 – dfeuer 2015-02-23 05:53:05

+2

你打算让Kg和Lb加在一起吗?否则,请考虑使用幻像类型来静态保证这不会发生。 – chi 2015-02-23 09:26:29

回答

5

您可以使用警卫。下面的代码是一个错误,因为我相信你已经注意到:

instance Num Weight where 
    Wt x a + Wt y a = Wt (x + y) a 
    -- ... 

但是,这是罚款:

instance Num Weight where 
    Wt x a + Wt y b | a == b = Wt (x + y) a 
    -- ... 

只要记住,如果有人试图公斤添加到磅,你的代码将会出错,除非你也处理这种情况。

+0

完美,谢谢!我有一个'convert'函数,所以我应该可以这样做:'Wt x a + Wt y b | a == b = Wt(x + y)a否则= Wt x a +(convert(Wt y b))'right? – ephrion 2015-02-23 03:31:45

+1

这似乎应该工作。不要忘记'否则'子句需要换行符和另一个垂直条。 – 2015-02-23 03:34:53