[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