[Haskell-cafe] Adding Ord constraint to instance Monad Set?

Simon Peyton-Jones simonpj at microsoft.com
Wed Mar 31 09:08:54 EST 2004


Alex

| Following the declaration of "instance Monad []"
| in the prelude, and puzzling over the absence of
| its equivalent from Data.Set, I naively typed:
| 
|    instance Monad Set where
| 	m >>= k = concatSets (mapSet k m)
| 	return x = unitSet x
| 	fail s = emptySet
| 
|    concatSets sets = foldl union emptySet (setToList sets)
|    instance (Eq b,Ord b) => Ord (Set b) where
| 	compare set1 set2 = compare (setToList set1) (setToList set2)
| 
| and got the following error:
| 
|     Could not deduce (Ord b) from the context (Monad Set)
|       arising from use of `concatSets' at dbMeta3.hs:242

I'm sorry to say that you just can't make Set an instance of Monad.  

To make an instance of Monad for a type constructor T you must have a
function

	bindT :: forall a b. T a -> (a -> T b) -> T b

And there just *is* no such function for Set, because of the need for
ordering.  There's a less polymorphic function

	bindSet :: forall a b. (Ord a, Ord b) 
		  => T a -> (a -> T b) -> T b

To see why this is no good, consider

	sequence :: Monad m => [m a] -> m [a]

The code for sequence calls (>>=) a lot.   You can't supply bindSet as
the function to call because bindSet takes two Ord parameters at
run-time, whereas ordinary bind does not.  It's not just a quirk of the
type system -- there is a real problem!

Simon




More information about the Haskell-Cafe mailing list