繁体   English   中英

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

[英]How does Haskell infer definitions for type classes?

所以我在和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如何在仅给出单个定义的情况下为其他比较运算符推断定义?

谢谢!

其余的仅使用(<=) (或compare )与类型类一起实现-这就是此处文档中的“最小实现”: http : //hackage.haskell.org/package/base-4.7.0.1/ docs / Prelude.html#t:Ord的意思。

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

可悲的是,在这种情况下,您无法直接显示来自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(<=)所有其他内容都将出现。

必须说Ord类型类适用于总顺序类型,而复数不满足总顺序的属性。 特别是,您的实现违反了反对称属性,即,

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

不满足此属性将违反Ord的约定,并可能导致奇怪的错误,具体取决于实例的使用方式。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM