There is a small performance difference. Keeping track of the
() requires an extra pointer which means it will take in more space. Many of the functions also need to be changed anyway to make the interface nicer.
And now that I’m thinking about it, you could also implement Map in terms of Set:
data KeyValue k v = KeyValue !k v
instance Eq k => Eq (KeyValue k v) where
KeyValue k1 _ == KeyValue k2 _ = k1 == k2
instance Ord k => Ord (KeyValue k v) where
compare (KeyValue k1 _) (KeyValue k2 _) = compare k1 k2
type Map k v = Set (KeyValue k v)
I think either way has performance implications, untill something like unpacking polymorphic fields will be implemented.
Edit: I think we can actually already do something like that with backpack, see:
unpacked-containers. Now I have to go try this out…
And the implementations of Set and Map are not that large. On the other hand I think a lot of bugs are caused by this kind of code duplication (e.g. this bytestring issue I found).