所以我在研究 Haskell 时发现了一些让我困惑的事情。我定义了一个复杂的 float 据结构,并想在其上使用比较运算符。最初我这样做效果很好:
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意思是。
Minimal complete definition: either compare or <=. Using compare can be more efficient for complex types.
遗憾的是,在这种情况下,您不能直接从 Hackage 显示源代码,而是显示为 Ord a
暗示 Eq a
不难想象这是如何做到的。
例如你有 (<=)
已实现 (<)
可以只是:
a < b = a /= b && a <= b
你得到了
a >= b = not (a < b)
最后
a > b = not (a <= b)
或类似的东西。
顺便说一句,正如您在第一次实现中可能看到的那样,您没有实现 compare
, max
或 min
即使它是类型类的一部分,它也会被推断出来。
也许你可以自己猜猜。
备注
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
或 (<=)
其他一切都接踵而至。
关于haskell - Haskell 如何推断类型类的定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26396162/