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.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe