Полагаю, то, что я хочу, невозможно без Template Haskell, но я все равно спрошу.
У меня есть интерфейс для таких типов, как Data.Set
и Data.IntSet
:
type family Elem s :: *
class SetLike s where
insert :: Elem s -> s -> s
member :: Elem s -> s -> Bool
...
type instance Elem (Set a) = a
instance Ord a => SetLike (Set a) where
...
И у меня есть семейство типов, которое выбирает реализацию оптимального набора:
type family EfficientSet elem :: *
type instance EfficientSet Int = IntSet
type instance EfficientSet String = Set String -- or another implementation
Есть ли способ гарантировать, что EfficientSet
экземпляры всегда будут SetLike
и что Elem (EfficientSet a)
равно a
?
Без этой гарантии все сигнатуры функций будут выглядеть следующим образом:
type LocationSet = EfficientSet Location
f :: (SetLike LocationSet, Elem LocationSet ~ Location) => ...
Писать каждый раз SetLike LocationSet
несколько терпимо, но Elem LocationSet ~ Location
затрудняет понимание кода, как для меня.