
I'm not actually bothered about every possible monad being representable as such in Haskell. I'd just like Set to work. ;-)
What would "work" mean in this case? I see two different meanings: 1. Use monadic operations (mapM, guard) on Sets. How would you decide which operations are allowed and which aren't? A possible answer would be: if you can add an implicit Ord constraint for every argument of m (where m is constrained to be a Monad), you can instantiate m as Set. So sequence :: (Monad m) => [m a] -> m [a] would work since [a] is an instance of Ord whenever a is but ap :: (Monad m) => m (a -> b) -> m a -> m b wouldn't since we can't have a (meaningful) Ord instance for a -> b even if a and b are themselves instances. Such a mechanism is, of course, broken. Consider the following alternative definition for liftM2: liftM2 :: (Monad m) => (a -> b -> c) -> m a -> m b -> m c liftM2 f ma mb mc = return f `ap` ma `ap` mb `ap` mc -- deliberately avoiding Applicative and Functor While the type of liftM2 indicates it should work (and the definition found on GHC actually does), in this case it would utterly break at the "return f" and the "ap"s. In other words, one can't rely on the type alone to know whether a monadic operation is applicable to Set. In OOP, I think they'd call this a violation of Liskov's Substitution Principle. 2. Make the nice monadic syntax work for sets. In this case I'd restate the problem as not being able to extend Haskell's syntax within your program (a problem shared by most non-Lisp languages). While TH provides a fairly decent solution in this respect, it's still far from Lisp's flexibility. In this respect, does anyone know how the Liskell project is doing? The site and mailing list seem pretty silent... -- Ariel J. Birnbaum