On Thu, Sep 08, 2005 at 09:30:34AM -0700, Scherrer, Chad wrote:
One of Mark Jones's articles suggests something like
class Plus a b c | a b -> c where (+) :: a -> b -> c
Would
instance (Plus a b c, Monad m) => Plus (m a) (m b) (m c) where mx + my = do x <- mx y <- my return (x + y)
do what you're looking for?
Hi Chad, I'm not sure exactly what you have in mind. Obviously I want something that applies to all functions, with any number of arguments, and not just (+). Furthermore, it should handle cases like 1+[2,3] where only one value is monadic. Keean Schupke's suggestion sounds more likely to be useful, but I'm still reading it. In any case, a minimum of syntactic overhead is desired. Frederik
------------------------------------------------------------------ Original message:
Hi,
Sean's comment (yeah, it was like a billion years ago, just catching up) is something that I've often thought myself.
I want the type system to be able to do "automatic lifting" of monads, i.e., since [] is a monad, I should be able to write the following:
[1,2]+[3,4]
and have it interpreted as "do {a<-[1,2]; b<-[3,4]; return (a+b)}".
Also, I would have
Reader (+1) + Reader (+4) == Reader (\x -> 2*x+5)
The point I want to make is that this is much more general than IO or monads! I think we all understand intuitively what mathematicians mean when they add two sets
{1,2}+{3,4} (i.e. { x+y | x\in {1,2}, y\in {3,4}})
or when they add functions
(f+g)(x) where f(x)=x+1 and g(x)=x+4
So "automatic lifting" is a feature which is very simple to describe, but which gives both of these notations their intuitive mathematical meaning - not to mention making monadic code much tidier (who wants to spend their time naming variables which are only used once?). I think it deserves more attention.
I agree that in its simplest incarnation, there is some ugliness: the order in which the values in the arguments are extracted from their monads could be said to be arbitrary. Personally, I do not think that this in itself is a reason to reject the concept. Because of currying, the order of function arguments is already important in Haskell. If you think of the proposed operation not as lifting, but as inserting `ap`s:
return f `ap` x1 `ap` ... `ap` xn
then the ordering problem doesn't seem like such a big deal. I mean, what other order does one expect, than one in which the arguments are read in the same order that 'f' is applied to them?
Although it is true that in most of the instances where this feature would be used, the order in which arguments are read from their monads will not matter; yet that does not change the fact that in cases where order *does* matter it's pretty damn easy to figure out what it will be. For instance, in
print ("a: " ++ readLn ++ "\nb: " ++ readLn)
two lines are read and then printed. Does anybody for a moment question what order the lines should be read in?
Frederik