
On 08/01/06, Brian Hulley
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