[Haskell-cafe] Crazy idea: overloading function application notation

Claus Reinke claus.reinke at talk21.com
Thu May 31 07:40:27 EDT 2007


> This is a crazy idea I've been working on: overload the syntax "x y" so it can 
> mean function application "f x = f(x)" or multiplication "x y = x*y". The 
> reason is simply that I appreciate the brevity of MLs function application 
> but I also appreciate the brevity of Mathematica's multiplication.
> 
> Is it possible to implement this in Haskell using type classes? Is there any 
> way this could actually be practicable?

i'm not sure about practicalities - since Haskell programs are mostly
identifiers and their applications, redefining application is going to
lead to confusion. general rule for extending pure functional languages:
do not mess with application, or you risk losing your nice theory.
a rather steep price to pay for replacing '*' with ' ', no?

you could, however, define a 'Num' instance for functions so that
'f * g = f . g' and 'fromInteger n = fromInteger . const n' or similar 
(though the types are not likely to make you happy), or you could 
try replacing the standard 'Num' class with one permitting differently-
typed parameters to '(*)', and then try to define multiplication as
application rather than composition.. (and if you think that is 
confusing, think again about overloading application;-)

the rest of this message will not help with your particular problem, but
is in reply to your subject line: in general, Haskeller's like to enjoy
the advantages of overloading something so fundamental as application
without endangering that fundament, even if that means a little more
typing to indicate where a non-standard overloading is possible. so
overloaded application uses a different notation and conventions. 
recall that '($)' is function application, and consider the following types:

    flip ($) :: a -> (a -> b) -> b
    (>>=) :: (Monad m) => m a -> (a -> m b) -> m b

you'll notice that monadic bind corresponds to reverse function
application, lifted into a monad. of course, there are many ways to do
such lifting, so it is interesting to consider what the particular
choice of monadification here means.

if we permit monadic effects in all of parameter, function, and result,
we'd get a type like this for lifted, reversed function application:

    m a -> m (m a -> m b) -> m b

the type of '(>>=)' differs from this in two positions, meaning no
monadic effects while computing the function, and no monadic effects in
the function parameter _after_ substitution into the function body. the
latter implies that, even though Haskell's standard application is based
on call-by-need (or call-by-name, since sharing isn't required), its
monadic application is based on call-by-value: any monadic effects in
computing the argument have to be executed _before_ passing the 
(effect-free part of the) argument to the function.

i've often wondered about this discrepancy.

but if you just want overloaded application, rather than mess with the
meaning and notation of built-in application, Monads may be the way to
go. it might also give one indication of why Monads are so popular in
Haskell, and so little heard of in languages which do allow
unconstrained overloading of application.

claus




More information about the Haskell-Cafe mailing list