2016-09-21 83 views
0

我有一个看起来像这样的类型,我想compare函数只考虑整数的大小。Haskell实例Ord困难

data Cell = FromLeft Coordinate Int 
      | FromTop Coordinate Int 
      | FromDiagonal Coordinate Int 
      | Empty Coordinate 
    deriving (Eq, Read, Show) 

下面的代码工作,但我宁愿东西更优雅

instance Ord Cell where 
    compare (FromLeft _ x) (FromLeft _ y) = compare x y 
    compare (FromRight _ x) (FromLeft _ y) = compare x y 
    [...] 
+0

这不是一个好的Ord实例,因为即使它们在“坐标”字段中不同,它们的比较值也是相等的。另外,'Empty'应该如何比较? – leftaroundabout

+0

@leftroundabout是的,你让我意识到'''Ord'''真的不是我所追求的。就像在Haskell中一样,你花费了大量时间来解决类型系统问题,只是意识到你应该一直在倾听它。 – davorb

+0

您可能会考虑为您的Ord实例定义一个新类型,而不是直接在Cell中定义它(就像没有用于任何数值类型的Monoid实例,而是用于Product和Sum的单独实例一样)类型)。 – chepner

回答

4

你可以定义一个辅助功能:

extractInt :: Cell -> Int 
extractInt (FromLeft _ x) = x 
extractInt (FromTop _ x) = x 
extractInt (FromDiagonal _ x) = x 
extractInt Empty = ??? 

然后

instance Ord Cell where 
    compare c1 c2 = compare (extractInt c1) (extractInt c2) 

但是要小心:上面的实例违反反对称定律,如果x<=yy<=x然后x==y。所以它并不是真的定义一个订单而是一个预订。