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

rya*_*yan 2 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)
Run Code Online (Sandbox Code Playgroud)

但我也注意到刚刚声明:

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)
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

Car*_*ten 5

其余部分仅使用(<=)(或compare)使用类型类实现- 这是此处文档中的“最小实现”:http : //hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html #t:顺序平均。

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

遗憾的是,在这种情况下,您无法直接从 Hackage 显示源代码,但正如Ord a所暗示Eq a的那样,不难想象这是如何完成的。

例如,你已经(<=)实施(<)可以只是:

a < b = a /= b && a <= b
Run Code Online (Sandbox Code Playgroud)

你得到

a >= b = not (a < b)
Run Code Online (Sandbox Code Playgroud)

最后

a > b = not (a <= b)
Run Code Online (Sandbox Code Playgroud)

或类似的东西。

顺便说一句,正如您在第一个实现中看到的那样compare,您没有实现,max或者min即使它是类型类的一部分,并且它也被推断出来了。

或许你可以试着自己猜一猜。

评论

大卫找到了来源 - 这是从那里开始的实施:

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 | (<=) #-}
Run Code Online (Sandbox Code Playgroud)

如您所见:如果您有compare(<=)其他所有内容如下。

  • 作为参考,可以在此处找到默认定义(以及 `Ord` 类的其余部分)的来源 https://github.com/ghc/ghc/blob/master/libraries/ghc-prim/GHC/Classes。 hs#L128。 (3认同)