Could not deduce (Eq a) from (Num a) or from (Floating a). But Can deduce (Eq a) from (Integral a). Why?

孤人 提交于 2020-03-17 10:18:00

问题


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 :)


回答1:


Short answer

Because that's the definition of Num in the prelude:

class Num a where
    ...

Whereas the definition for Integral requires the type to be Real and Enum:

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

And Real implies both Num and Ord...

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

And Ord, naturally, implies Eq:

class Eq a => Ord a where
    ...

This line means that in order to make something implement Ord, it must also implement Eq. Or we could say that Ord is a subclass of Eq. Anyway...

The summary is that Num is not a subclass of Eq, but Integral is a subclass of Eq.

Long answer (why?)

You can imagine implementing Num in ways that make it impossible to implement 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.

Here, Sequence is the type representing all computable sequences. You can't implement Eq in any reasonable way, because the sequences are infinitely long!

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..]]

So it makes sense that Num is not a subclass of Eq, because there are useful types which can implement Num but not Eq.



来源:https://stackoverflow.com/questions/18676468/could-not-deduce-eq-a-from-num-a-or-from-floating-a-but-can-deduce-eq-a

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!