15

I'm going through a haskell tutorial (Learn you a haskell for great good) and I was playing around with this code I wrote based of off one of the functions in the book.

reverseNum :: (Num a) => a -> a
reverseNum 123 = 321
reverseNum x = 0

and ghci tells me that it can't deduce (Eq a) from (Num a).

So I change the first line to this

reverseNum :: (Integral a) => a -> a

and it worked. This was strange because I thought to be a part of the Num typeclass you needed to also be apart of Eq.

I tried one more thing to satisfy me curiosity and changed the first 2 lines to this

reverseNum :: (Floating a) => a -> a
reverseNum 1.0 = 0.1

and it gave me the same error.

I know that you can fix this by doing something like reverseNum :: (Num a, Eq a) ... but I want to know why Integral is the only one where Eq can be deduced. Why is that?

P.S. I am really new to haskell so... be gentle :)

4

1 回答 1

30

简短的回答

因为这是Num序曲中的定义:

class Num a where
    ...

而 for 的定义Integral要求类型为Realand Enum

class (Real a, Enum a) => Integral a where
    ...

Real暗示两者NumOrd...

class (Num a, Ord a) => Real a where
    ...

并且Ord,自然地,意味着Eq

class Eq a => Ord a where
    ...

这条线的意思是,为了使某事实施Ord,它也必须实施Eq。或者我们可以说这OrdEq. 反正...

总结是Num不是 的子类Eq,而是Integral的子类Eq

长答案(为什么?)

您可以想象Num以无法实施的方式实施Eq

newtype Sequence = Sequence (Integer -> Integer)

instance Num Sequence where
  (Sequence x) + (Sequence y) = Sequence $ \pt -> x pt + y pt
  (Sequence x) - (Sequence y) = Sequence $ \pt -> x pt - y pt
  (Sequence x) * (Sequence y) = Sequence $ \pt -> x pt * y pt
  negate (Sequence x) = Sequence $ \pt -> -pt
  abs (Sequence x) = Sequence $ \pt -> abs pt
  signum (Sequence x) = Sequence $ \pt -> signum pt
  fromInteger = Sequence . const

-- Ignore the fact that you'd implement these methods using Applicative.

这里,Sequence是代表所有可计算序列的类型。您无法Eq以任何合理的方式实现,因为序列无限长!

instance Eq Sequence where
  -- This will never return True, ever.
  (Sequence x) == (Sequence y) =
      and [x pt == y pt | pt <- [0..]] &&
      and [x pt == y pt | pt <- [-1,-2..]]

Num所以它不是 的子类是有道理的Eq,因为有一些有用的类型可以实现Num但不能实现Eq

于 2013-09-07T18:40:24.620 回答