haskell - Associated data families and overlapping instances -
i'd 'generic' map data structure can efficiently specialized providing custom instances, in the ghc manual section on type families.
{-# language flexibleinstances #-} {-# language typefamilies #-} {-# language undecidableinstances #-} module mapkey import data.map.strict (map) import qualified data.map.strict map class mapkey k data mmap k :: * -> * instance {-# overlapping #-} mapkey () newtype mmap () v = unitmap (maybe v) instance {-# overlappable #-} ord k => mapkey k newtype mmap k v = ordmap (map k v)
sadly, doesn't work. ghc (8.2.1) complains:
conflicting family instance declarations: mmap () = unitmap (maybe v) mmap = ordmap (map k v) | 14 | newtype mmap () v = unitmap (maybe v) |
is there language extension allows this? otherwise there way make easy users define 'default' instance ord
?
one solution relinquishes overlapping instances use default associated injective type family (quite mouthful). attached methods default implementations default mmap
synonym:
{-# language defaultsignatures #-} {-# language typefamilies #-} {-# language typefamilydependencies #-} module mapkey import data.map.strict (map) import qualified data.map.strict map class mapkey k type mmap k v = r | r -> k v type mmap k v = map k v empty :: mmap k v default empty :: (mmap k v ~ map k v) => mmap k v empty = map.empty insert :: k -> v -> mmap k v -> mmap k v default insert :: (mmap k v ~ map k v, ord k) => k -> v -> mmap k v -> mmap k v insert = map.insert lookuple :: k -> mmap k v -> [(k, v)] default lookuple :: (mmap k v ~ map k v, ord k) => k -> mmap k v -> [(k, v)] lookuple k m = case map.lookuple k m of nothing -> [] e -> [e] instance mapkey () type mmap () v = maybe v empty = nothing insert _ v _ = v lookuple _ m = case m of nothing -> [] (just v) -> [((), v)]
this means client code still has define boilerplate orphan instances like
instance mapkey int
i'd rather see solution uses overlapping instances instead.
Comments
Post a Comment