リスト表現からツリーを復元するために必要な 1 つの型クラスを分解しようとしたときに、興味深い状況に陥りました。アイデアは、要素のプロパティを元の階層で互いに相対的に表現することでした。
データ型の次の特性を考慮する
class HierarchyOrd a where
-- | Compares two objects for being on the same branch of hierarchy
-- LT/GT lower/higher in hierarchy, EQ on the same node
hierarchyCompare :: a -> a -> Maybe Ordering
class HierarchyOrd a => Hierarchy a where
-- | Get information for common joint of branches for two objects
-- Either one of them already on joint node (parent)
-- or we need another object that represent that joint
hierarchyJoint :: a -> a -> Either Ordering a
-- hierarchyCompare x y = either Just (const Nothing) (hierarchyJoint x y)
-- Sample for FilePath
instance Hierarchy FilePath where
hierarchyJoint x y = case (length x', length y', length z') of
(a, b, c) | a == c && b == c -> Left EQ
(a, _, c) | a == c -> Left GT
(_, b, c) | b == c -> Left LT
_ -> Right (joinPath z')
where
[x', y'] = map splitDirectories [x, y]
skel = takeWhile id (zipWith (==) x' y')
z' = zipWith const x' skel -- common prefix
instance HierarchyOrd FilePath where
hierarchyCompare x y = either Just (const Nothing) (hierarchyJoint x y)
ご覧のとおり、新しいノードの構築を必要とせずに順序付けを実装するだけでよいHierarchyOrdering
のサブセットです。Hierarchy
この特定のケース ( FilePath
) では、重複しない 2 つの機能を持つことは実現不可能であり、余分な作業 ( と のディレクトリを 2 回分割する) が発生する可能性さえありhierarchyCompare
ますhierarchyJoint
。を取得した場合にそれを呼び出す意味がないため、 hierarchyCompare
byの機能をカバーすることにしたのはそのためです。hierarchyJoint
Just _
hierarchyCompare
問題は、 object が on で定義されている場合のデフォルトの実装をどのようにするかですHierarchy
。たぶん、型クラス間のそのような種類の関係をより説明的な方法で公開できるようにする拡張機能があります(デフォルトの実装を許可します)?