I suppose what I want is impossible without Template Haskell but I\'ll ask anyway.
I have an interface for types like Data.Set and Data.IntSet
I like Daniel Wagner's post, but you can't just write:
test :: (HasEfficientSet a) => EfficientSet a
test = empty
You have to write:
test :: (HasEfficientSet a, SetLike (EfficientSet a)) => EfficientSet a
test = empty
But this can be overcome with a constraint synonym:
class SetLike s where
type Elem s :: *
empty :: s
insert :: Elem s -> s -> s
member :: Elem s -> s -> Bool
class (Elem (EfficientSet a) ~ a) => HasEfficientSet' a where
type EfficientSet a :: *
type HasEfficientSet a = (HasEfficientSet' a, SetLike (EfficientSet a))
newtype UnitSet = UnitSet Bool
deriving (Show, Eq, Ord)
instance SetLike UnitSet where
type Elem UnitSet = ()
empty = UnitSet False
insert () _ = UnitSet True
member () u = UnitSet True == u
instance HasEfficientSet' () where
type EfficientSet () = UnitSet
test :: (HasEfficientSet a) => EfficientSet a
test = empty
test1 :: EfficientSet ()
test1 = empty
test2 :: EfficientSet ()
test2 = test
test3 :: UnitSet
test3 = empty
test4 :: UnitSet
test4 = test