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

Derek Elkins derek.a.elkins at gmail.com
Thu May 31 18:56:17 EDT 2007


Claus Reinke wrote:
>> 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;-)

Indeed.  This change would -definitely- lead to massive ambiguity and 
potentially lead to unresolvable cases.

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

Laziness "causes" Haskell to be pure because understanding side-effecting code 
in a lazy language is... tricky to say the least.  Why then would we want 
laziness for monads?  Also, nothing is stopping you from defining a "lazy" apply 
when you -do- want it.

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

Um... they are probably so little heard of in languages that allow unconstrained 
overloading of application because they are so little heard of in -any- other 
language.


More information about the Haskell-Cafe mailing list