【问题标题】:Could not deduce (Eq a) from (Num a) or from (Floating a). But Can deduce (Eq a) from (Integral a). Why?无法从 (Num a) 或 (Floating a) 推导出 (Eq a)。但可以从 (Integral a) 推导出 (Eq a)。为什么?
【发布时间】:2013-09-07 18:22:29
【问题描述】:

我正在学习一个 haskell 教程(向你学习一个很好的 haskell),我正在玩我根据书中的一个函数编写的这段代码。

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

ghci 告诉我它不能从 (Num a) 推导出 (Eq a)。

所以我把第一行改成这个

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

它奏效了。这很奇怪,因为我认为要成为 Num 类型类的一部分,你也需要成为 Eq 的一部分。

我又尝试了一件事情来满足我的好奇心,并将前 2 行改成了这个

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

它给了我同样的错误。

我知道您可以通过执行reverseNum :: (Num a, Eq a) ... 之类的操作来解决此问题,但我想知道为什么 Integral 是唯一可以推导出 Eq 的。 这是为什么呢?

附:我对haskell真的很陌生,所以...要温柔:)

【问题讨论】:

标签: haskell


【解决方案1】:

简答

因为那是前奏中Num的定义:

class Num a where
    ...

Integral 的定义要求类型为RealEnum

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的子类,但IntegralEq的子类。

长答案(为什么?)

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

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

【讨论】:

  • 击败我得到答案,你的措辞要好得多。投赞成票。
  • 重要的是要补充一点,这不是 Haskell 2010 Prelude 中Num 的定义;这正是 GHC 所做的。在 Haskell 2010 中,Num a 意味着 Eq aShow a
  • 等等……那为什么 Int 没有 Eq? int 不是 Integral 的子类型吗?
  • @thecodethinker:Int 是一个类型,它实现了Eq,这是一个类。所以Int 确实有Eq
  • 好吧...我想我只是在某个地方搞砸了。谢谢
猜你喜欢
  • 1970-01-01
  • 2023-03-19
  • 2019-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多