Haskell:为用户定义的newtypes实现Num instace

时间:2015-10-22 18:12:36

标签: haskell newtype

我有一个Pair新类型,它只是Double的一个元组,我希望能够使用这种类型的算术运算符。这是我的代码,无法编译:

module Test where                                   

newtype Pair = Pair (Double, Double)                

instance Num Pair where                             
  Pair (x1, y1) + Pair (x2, y2) = Pair (x1+x2, y1+y2
  Pair (x1, y1) - Pair (x2, y2) = Pair (x1-x2, y1-y2
  Pair (x1, y1) * Pair (x2, y2) = Pair (x1*x2, y1*y2
  abs (Pair (x, y)) = Pair (abs x, abs y)           
  signum (Pair (x, y)) = Pair (signum x, signum y)  
  fromInteger i = Pair (fromInteger i, fromInteger i)

func :: Pair -> Double -> Pair                      
func p d = p * d                                    

以下是erro GHC抛出:

[1 of 1] Compiling Test             ( test.hs, interpreted )

test.hs:14:16:
Couldn't match expected type `Pair' with actual type `Double'
In the second argument of `(*)', namely `d'
In the expression: p * d
In an equation for `func': func p d = p * d
Failed, modules loaded: none.

我原本以为定义from Integer*就足够了,有人可以告诉我做错了吗?

更新

如果我添加以下实例:

instance Fractional Pair where                          
  Pair (x1, y1) / Pair (x2, y2) = Pair (x1/x2, y1/y2)   
  fromRational r = Pair (fromRational r, fromRational r)

然后我的函数仍然没有编译,但在ghci中,我可以做

> Pair (1.0, 2.0) * 3.4
Pair (3.4,6.8)

但不是:

> Pair (1.0, 2.0) * 3.4 :: Double

<interactive>:206:1:
Couldn't match expected type `Double' with actual type `Pair'
In the return type of a call of `Pair'
In the first argument of `(*)', namely `Pair (1.0, 2.0)'
In the expression: Pair (1.0, 2.0) * 3.4 :: Double

我仍然在努力理解为什么会这样。

2 个答案:

答案 0 :(得分:3)

func :: Pair -> Double -> Pair
func p d = p * d

您尝试将Pair乘以Double,但*的两个参数必须具有相同的类型。

答案 1 :(得分:2)

你试图在一个参数上使用隐式fromInteger,这是没有道理的。

首先,fromInteger(或fromRational)仅隐含在文字上。即:

6 = fromInteger 6
4.1 = fromRational 4.1

但这不正确

a = fromInteger a  -- Not true!

您的论据d不是文字,因此您必须手动使用realToFrac :: (Real a, Fractional b) => a -> b

func :: Pair -> Double -> Pair
func p d = p * realToFrac d