Haskell如何推断类型类的定义?

时间:2014-10-16 04:19:48

标签: haskell

所以我正在玩Haskell并注意到让我困惑的事情。我定义了一个复杂的浮点数据结构,并希望在其上使用比较运算符。最初我做了这个工作得很好:

data Cplx = Cplx Float Float deriving (Eq, Show)

instance Ord Cplx where
  (<=) a b = (<=) (normCplx a) (normCplx b)
  (>=) a b = (>=) (normCplx a) (normCplx b)
  (<) a b = (<) (normCplx a) (normCplx b)
  (>) a b = (>) (normCplx a) (normCplx b)

normCplx :: Cplx -> Float
normCplx (Cplx a1 a2) = sqrt( a1^2 + a2^2)

但我也注意到只是声明:

data Cplx = Cplx Float Float deriving (Eq, Show)

instance Ord Cplx where
  (<=) a b = (<=) (normCplx a) (normCplx b)    

normCplx :: Cplx -> Float
normCplx (Cplx a1 a2) = sqrt( a1^2 + a2^2)

也完成了工作。如果仅给出单一定义,Haskell如何推断其他比较运算符的定义?

谢谢!

2 个答案:

答案 0 :(得分:4)

其余部分仅使用(<=)(或compare)的类型类实现 - 这就是&#34;最小的实现&#34;在这里的文档中:http://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#t:Ord意思是。

  

最小完整定义:比较或&lt; =。使用比较可以   对复杂类型更有效。

可悲的是,在这种情况下,您无法直接从Hackage中显示来源,但由于Ord a暗示Eq a,因此不难想象这是如何完成的。

例如,您(<=)实施(<)只能是:

a < b = a /= b && a <= b

你得到

a >= b = not (a < b)

和最终

a > b = not (a <= b)

或类似的东西。

顺便说一下,您在第一次实施中可能已经看到,即使它是类型类的一部分,您也没有实现comparemaxmin也被感染了。

也许你可以尝试自己猜测。

备注

David找到了消息来源 - 这是从那里实现的:

class  (Eq a) => Ord a  where
    compare              :: a -> a -> Ordering
    (<), (<=), (>), (>=) :: a -> a -> Bool
    max, min             :: a -> a -> a

    compare x y = if x == y then EQ
                  -- NB: must be '<=' not '<' to validate the
                  -- above claim about the minimal things that
                  -- can be defined for an instance of Ord:
                  else if x <= y then LT
                  else GT

    x <  y = case compare x y of { LT -> True;  _ -> False }
    x <= y = case compare x y of { GT -> False; _ -> True }
    x >  y = case compare x y of { GT -> True;  _ -> False }
    x >= y = case compare x y of { LT -> False; _ -> True }

        -- These two default methods use '<=' rather than 'compare'
        -- because the latter is often more expensive
    max x y = if x <= y then y else x
    min x y = if x <= y then x else y
    {-# MINIMAL compare | (<=) #-}

如您所见:如果您有compare(<=),则其他所有内容都会出现。

答案 1 :(得分:1)

必须说Ord类型类是针对total order的类型,复数不满足总排序的属性。特别是,您的实现违反了反对称属性,即

forall a b. if a ≤ b and b ≤ a then a = b.

未能满足此属性违反了Ord的合同,可能会导致奇怪的错误,具体取决于实例的使用方式。

normCplx应用于您可能依赖于Ord派生的功能,例如sortBy (compare `on` normCplx)您可能刚刚使用sort的情况,可能更合适。< / p>