Ariel J. Birnbaum valgarv at gmx.net
Sat Sep 27 18:46:37 EDT 2008

```> 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
```