2012-12-15 68 views
3

當我嘗試分解一個需要從列表表示中恢復樹的類型類時,我遇到了一個有趣的情況。這個想法是表示元素的屬性在原始層次結構中是相對於其他元素的。Typeclass是Haskell中另一個和默認實現的超集

考慮數據類型

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) 

的下一個特質正如你所看到HierarchyOrderingHierarchy一個子集,我們只需要實現排序,無需建設新的節點。在這種特殊情況下(FilePath)具有兩個不重疊的功能是不可行的,甚至可能導致額外的工作(爲hierarchyComparehierarchyJoint分裂目錄兩次)。這就是爲什麼決定通過hierarchyJoint覆蓋hierarchyCompare的功能,因爲如果我們得到Just _就沒有意義了。

問題是:當在Hierarchy上定義對象時,如何使用默認實現hierarchyCompare。也許有一些擴展允許以更具描述性的方式暴露類型類之間的這種關係(允許默認實現)?

回答

5

我認爲你正在尋找的GHC DefaultSignatures擴展?它可以讓你做的事:

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 
    default hierarchyCompare :: Hierarchy a=> a -> a -> Maybe Ordering 
    hierarchyCompare x y = either Just (const Nothing) (hierarchyJoint x y) 

,然後你可以簡單地提供一個空的實例聲明:

instance HierarchyOrd FilePath 
+0

是的,這就是我一直在尋找的。我的確希望這個擴展有點不同的設計。特別是當我有幾個超集時,會有一個問題。但是這個變體也允許有更復雜的上下文而不僅僅是一個類型'Hierarchy a'。謝謝 – ony

0

有沒有這樣的擴展(還)。

現在,你能做的最好的是

defaultHierarchyCompare :: Hierarchy a => a -> a -> Maybe Ordering 
defaultHierarchyCompare x y = either Just (const Nothing) (hierarchyJoint x y) 

instance Hierarchy FilePath where ... 

instance HierarchyOrd FilePath where 
    hierarchyCompare = defaultHierarchyCompare 
+1

是的,這是標準方式,例如['Traversable'](http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Traversable.html):它定義了'fmapDefault'和'fol​​dMapDefault'作爲'Foldable'和'Functor'的實現。 –

3

只需添加到@ dave4420的和@ jberryman的anwers:與DefaultSignatures的問題是,你需要在超類中描述你的默認實現,而不是在它更符合邏輯的子類中。所以不可能將類型類拆分成不同的模塊等。有一種方案可以解決各種類似的問題,稱爲Default superclass instances。不幸的是它還沒有實現。