[Haskell] Mixing monadic and non-monadic functions

Scherrer, Chad Chad.Scherrer at pnl.gov
Thu Sep 8 12:30:34 EDT 2005


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?

Chad Scherrer
Computational Mathematics Group
Pacific Northwest National Laboratory

"Time flies like an arrow; fruit flies like a banana." -- Groucho Marx

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




More information about the Haskell mailing list