I guess the following probably works. As per the comments, it's still a terrible, terrible, terrible idea. If you really want to write Haskell like this, then you don't really want to write Haskell.
Anyway, the idea is to provide a type class for:
insert :: (Ord k) => k -> v -> a
parameterized in all three parameters with a functional dependency specifying that a determines k and v. In your case, a ~ (Map k' v' -> Map k' v') implies k ~ k' and v ~ v', while a ~ Set t implies k ~ t and v ~ Set t.
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies,
NoMonomorphismRestriction #-}
module UnifiedInsert where
-- insert :: Ord k => k -> v -> Map k v -> Map k v
-- insert :: Ord a => a -> Set a -> Set a
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Set (Set)
import qualified Data.Set as Set
class Insert k v a | a -> k, a -> v where
insert :: (Ord k) => k -> v -> a
instance Insert k (Set k) (Set k) where
insert = Set.insert
instance Insert k v (Map k v -> Map k v) where
insert = Map.insert
fromList = foldr insert mempty
foo1 :: Set Int
foo1 = fromList [1..10]
Note that the type checker can deduce the type of the function fromList (even if foo1 is dropped from the program), as long as the monomorphism restriction is off. It will have the rather preposterous type:
fromList :: (Foldable t, Insert k v v, Ord k, Monoid v) => t k -> v
which can, indeed, be specialized to Ord a => [a] -> Set a, as required.
insert :: Ord k => k -> v -> Map k v -> Map k vandinsert :: Ord a => a -> Set a -> Set a. Yes, I know that this might be a bad idea and that some people might not like it. But I don't force anyone to use this approach. I just interested whether it's possible or not.insertMapandinsertSetto separate use cases. But it's less convenient since historically name isinsertfor different types :( I don't think this is only coincidence becauseSet acan be just a special case ofMaplikeMap a (). But it's not convenient to insert()manually.foowere uncurried tofoo :: (a, b) -> x -> x, it would make more sense to unifyfooandbar.