Haskell 等式如何适用于数字类型?

Haskell 等式如何适用于数字类型?,haskell,typeclass,Haskell,Typeclass,我看到Haskell允许比较不同的数值类型: *Main> :t 3 3 :: Num t => t *Main> :t 3.0 3.0 :: Fractional t => t *Main> 3 == 3.0 True 数字类型的Eq实例的源代码在哪里?如果我创建了一个新类型,比如ComplexNumber,我可以扩展==来处理它吗?(我可能希望没有虚部的复数可能等于实数。)“Haskell允许比较不同的数字类型”不,它不允许。Haskell实际上允许由相同的文

我看到Haskell允许比较不同的数值类型:

*Main> :t 3
3 :: Num t => t
*Main> :t 3.0
3.0 :: Fractional t => t
*Main> 3 == 3.0
True

数字类型的
Eq
实例的源代码在哪里?如果我创建了一个新类型,比如ComplexNumber,我可以扩展
==
来处理它吗?(我可能希望没有虚部的复数可能等于实数。)

“Haskell允许比较不同的数字类型”不,它不允许。Haskell实际上允许由相同的文本定义不同的类型。特别是,你可以

Prelude> let a = 3.7 :: Double
Prelude> let b = 1   :: Double
Prelude> a + b
4.7
OTOH,如果我用冲突类型显式声明这些,那么添加将失败:

Prelude> let a = 3.7 :: Double
Prelude> let b = 1   :: Int
Prelude> a + b

<interactive>:31:5:
    Couldn't match expected type ‘Double’ with actual type ‘Int’
    In the second argument of ‘(+)’, namely ‘b’
    In the expression: a + b
因为与您的前提相反,
==
,实际上要求双方具有相同的类型,因此您可以省略任何一方的签名,而无需更改任何内容:

Prelude> 3.0 == (3 :: Double)
True
事实上,即使没有任何类型注释,GHCi仍然将两边都视为
Double
。这是因为–在这种特殊情况下,
分数型
是共享数字类型的最强约束,对于
分数型
,默认类型为
双精度
。OTOH,如果两边都是整型文字,那么GHCi就会选择
整型
。例如,这有时会产生影响

Prelude> 10000000000000000 == 10000000000000001
False
但是


因为在后一种情况下,最后的1在浮点错误中丢失。

这里没有什么神奇的事情发生
3
可以是实数,也可以是整数,但与
3.0
相比,它的类型与实数是统一的

请注意类型类:

class Eq a where
  eq :: a -> a -> Bool
因此,
eq
实际上只比较相同类型的事物。您的示例
3==3.0
将其类型统一,并在内部成为
3.0==3.0


我不确定是否有任何类型技巧可以让它与用户定义的复数类型统一起来。我的直觉告诉我这是不可能的。

这只是GHCi中(扩展的?)默认规则的一个例子。这里可能有一个混淆点:虽然
3
3.0
有不同的多态类型,但在表达式
3==3.0
中,它们在计算相等之前都被赋予相同的单态类型。
(==)
的类型表示它必须接受两个类型相同的参数:
Eq a=>a->a->Bool
。我怀疑这种微妙的误解是导致这个问题的原因,“允许比较不同的数字类型”。试试这个:
length“abc”==3.0
。行得通吗?@n.m.在GHCi中行得通。什么版本的GHCi?谢谢。所以我无法测试我创建的新类型的元素的相等性?不是从先前存在的类型,不是。甚至不是您也创建的其他类型。您只能将type
a
与type
a
@espertus进行比较:您可以轻松比较两个值,它们都是您自己创建的新类型。只需为该类型编写一个实例。这是可以做到的。看看这个:现在,如果这个默认机制更普遍,我会更高兴。。。
Prelude> 10000000000000000 ==(10000000000000001 :: Double)
True
class Eq a where
  eq :: a -> a -> Bool