只需将边缘连接的顶点视为无序集 (巧合的是卡片2)而不是两个单独的元素 以任意顺序:
instance Ord Edge where compare e1@(Edge x1 y1) e2@(Edge x2 y2) = compare (sort [x1,y1]) (sort [x2,y2])
甚至使用实际集:
data EdgeS = EdgeS (Set Int) deriving (Show, Eq) instance Ord EdgeS where compare (EdgeS a) (EdgeS b) = compare a b
甚至可以推导出这个实例(至于 Eq )。如果你愿意,你可以创建一个特殊的构造函数:
Eq
mkEdge : Int -> Int -> EdgeS mkEdge a b = EdgeS (S.fromList [a,b])
还有一些测试:
> compare (mkEdge 1 2) (mkEdge 2 1) EQ > compare (mkEdge 1 2) (mkEdge 3 1) LT > compare (mkEdge 1 2) (mkEdge 1 3) LT
我的答案类似于Thomas的,除了我建议你在构造边缘时进行标准化。
mkEdge :: Int -> Int -> Edge mkEdge x y | x <= y = Edge x y | otherwise = Edge y x
现在您知道具有较小索引的顶点首先出现,而且 deriving (Eq, Ord) 实例将完全符合您的要求。你只需要确保你只用它创建边 mkEdge “智能构造”(你可以通过推杆来做到这一点) Edge 在一个模块而不是导出 Edge 构造函数)。
deriving (Eq, Ord)
mkEdge
Edge