3

当我尝试分解从列表表示恢复树所需的一个类型类时,我遇到了一个有趣的情况。这个想法是表示元素的属性在原始层次结构中相互关联。

考虑数据类型的下一个特征

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) 具有两个不重叠的功能是不可行的,甚至可能导致额外的工作(为hierarchyCompare和拆分目录两次hierarchyJoint)。这就是为什么决定涵盖hierarchyCompareby 的功能,hierarchyJoint因为如果我们得到Just _.

问题是:hierarchyCompare当对象定义在Hierarchy. 也许有一些扩展允许以更具描述性的方式公开类型类之间的这种关系(允许默认实现)?

4

3 回答 3

5

我认为您正在寻找 GHCDefaultSignatures扩展?那让你做:

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 
于 2012-12-16T02:01:57.907 回答
3

只是添加到@dave4420 和@jberryman 的答案:问题DefaultSignatures是您需要在超类中描述您的默认实现,而不是在更符合逻辑的子类中描述。所以不可能将类型类拆分成不同的模块等。有一个提案可以解决各种类似的问题,称为默认超类实例。不幸的是,它还没有实施。

于 2012-12-16T10:52:33.423 回答
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
于 2012-12-15T22:19:03.810 回答