Typeclass which is superset of another and default implementations in Haskell

haskell, programming-languages, typeclass

Solution

I think you're looking for the GHC `DefaultSignatures` extension? That let's you do:

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)

and then you can simply provide an empty instance declaration:

instance HierarchyOrd FilePath 

Problem

I've came to an interesting situation when I tried to decompose one typeclass I needed for restoring tree from a list representation. The idea was to represent property of elements to be relative each to other in original hierarchy. Consider next traits of data types ``` 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) ``` As you can see `HierarchyOrdering` is a subset of `Hierarchy` for which we only need to implement ordering without requiring of building new node. In this particular case (`FilePath`) having two non-overlapping functionality isn't feasible and even may result in extra-work (splitting directories twice for `hierarchyCompare` and `hierarchyJoint`). That's why it was decided to cover functionality of `hierarchyCompare` by `hierarchyJoint` since it makes no sense to call it if we got `Just _`. Question is: how to be with default implementation of `hierarchyCompare` when object is defined on `Hierarchy`. Maybe there is some extension that allows to expose such kind of relation between typeclasses in a more descriptive way (wich allows default implementation)?

Original source