[Haskell-cafe] Avoiding name collisions by using value spaces instead of modules

Cale Gibbard cgibbard at gmail.com
Sun Jan 8 19:39:47 EST 2006

On 08/01/06, Brian Hulley <brianh at metamilk.com> wrote:
> Cale Gibbard wrote:
> > <snip>
> Thanks for the illustration - I see another advantage with type classes is
> that you only need to write the type signature once (in the class
> declaration) instead of before each instance binding.
> > Secondly, if the functions are really different, and you never plan to
> > use them polymorphically, why the heck would you want to call them the
> > same thing? That's just confusing to anyone that has to read the code
> > later.
> For example, Data.Map declares:
> insert :: Ord k => k -> a -> Map k a -> Map k a
> whereas Data.Set declares:
> insert :: Ord a => a -> Set a -> Set a
> This is an example where type classes can't be applied even though the
> functions in a sense do the same thing. My system would solve this problem,
> by allowing the programmer to type d = insert a b c and have the type
> inference algorithm work out that Data.Map.insert was meant, as long as c or
> d has been typed as Map p q.
> But perhaps there is a way to get the signature for Data.Map.insert into the
> same form as that of Data.Set.insert?
> Regards, Brian.

Well, that's an interesting case, since the types are actually
reasonably different. Prior to these being named the same way, we had
addToSet / addToFM, which didn't require qualified imports. Of course,
with qualified imports, we get the same effect as postfixing, so it's
basically the same thing.

Unifying these two under a single operation is certainly trickier, and
it's a little more questionable that it should be done at all, given
that their types are so different -- below is the closest I could come
to it off-hand.

{-# OPTIONS_GHC -fglasgow-exts #-} -- for fundeps/multiparameter classes
import qualified Data.Map as Map
import Data.Map (Map)
import qualified Data.Set as Set
import Data.Set (Set)

class Insert t c a | c a -> t where
    insert :: t -> c a -> c a

instance (Ord a) => Insert a Set a where
    insert x s = Set.insert x s

instance (Ord k) => Insert (k,a) (Map k) a where
    insert (k,v) m = Map.insert k v m

exampleSet = insert 5 $ insert 6 $ Set.empty
exampleMap = insert (1,2) $ insert (2,7) $ Map.empty


Perhaps someone else will have some ideas as to suitable typeclass
magic to allow for the curried form rather than using tuples.

 - Cale

More information about the Haskell-Cafe mailing list