Полагаю, то, что я хочу, невозможно без 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
только усложняет понимание кода, как по мне.