[Haskell-cafe] Desugaring of infix operators is (always?) the
wrong way round
Brian Hulley
brianh at metamilk.com
Thu Sep 27 10:37:26 EDT 2007
Sam Hughes wrote:
> Brian Hulley wrote:
>
>> ... For example, with the prefix definition of a function with
>> multiple clauses, the function name at the start of each clause is
>> already lined up since it must appear at the margin of the current
>> layout block ...
>
> Or you could have everything be backwards, and use an editor that
> right aligns things.
>
>
> (a -> b) -> [a] -> [b] :: map
> [] = [] _ map
> x f : xs f map = (x:xs) f map
>
There is still a reversal here between the order of arguments in the
type signature and the order in the clauses.
Henning Thielemann wrote:
>
>
> Curried functions like
>
> f :: a -> b -> c
>
> suggest a swapped order of arguments for (->), since 'f' must be
> called this way
>
> b a f
>
> Maybe it should be
>
> f :: c <- b <- a
>
>
Which would fix this reversal. However there are 2 other kinds of
reversal with postfix notation:
1) Declarations start with a keyword followed by some content whereas
function definitions start with the args followed by the function name
2) Special constructs like "case" or "let" have to start with the
keyword (so the parser knows what kind of thing it is supposed to parse
next and so that the editor knows how to highlight what the user is
typing before the user has finished typing the whole construct), again
making a reversal between built-in constructs and constructs you can
define using higher order functions (eg consider "if" as a user-defined
construct in a postfix language)
I've come to the conclusion that whereas postfix notation is extremely
neat for simple stack-based languages like Forth and PostScript it would
not play well with languages which have a structured syntax since
structured syntax + left to right reading order implies each syntactic
element must start with a "head" followed by content appropriate to that
element, or else recursive descent parsing and/or as-you-type
grammatical highlighting would be impossible, and therefore in terms of
function application, the "head" must of course be the function itself
hence Prefix is the only solution.
Jonathan's comparison to natural languages made me think of it this way:
x `plus` y === [Subject] [Verb] [Object]
x .plus(y) === [Subject] [Verb Object]
plus y x === [Verb Object] [Subject]
plus x y === [Verb Subject] [Object]
which illustrates why infix notation feels natural (corresponds to SVO
in English etc), why OOP notation feels natural, why prefix notation is
natural for a functional language (since we are interested primarily in
the transformation not the things being transformed hence we put [VO]
first), and why the desuraging of infix in Haskell/ML is quite simply
just wrong, since the object is now separated from the verb.
ok wrote:
> Binary operators have two arguments. That's why sections are needed.
What's wrong with just using (flip)?
>
>
> I am a bear of very little brain, and I would find it VERY confusing
> if the order of arguments in an operator application did not match
> the order of arguments in a function call. I can live with
> x @ y = (op @)(x, y) (* SML *)
> x @ y = (@) x y -- Haskell
> but making the orders different would guarantee that I would *always*
> be in a muddle about which argument was which. Living with
> inconvenient argument orders is vastly easier than with inconsistent
> ones.
If you inwardly parse x @ y as [x] [@ y] then the prefix notation is
naturally formed just by putting the "specialized verb" before the
subject instead of after it ie [@ y] [x].
Therefore I think this desugaring, though different from the usual one,
would seem natural as soon as the reason for it was understood (of
course, only if you agree with the reason ;-) ), and the great advantage
of it is that we could write library functions without having to decide
in advance whether or not they should be used with infix sugar.
(Regarding Henning's point about ((->) a) being needed for Reader monads
we could define "type Fun a b = a -> b" and then use (Fun a))
In any case, thanks to all who replied. I've found the discussion very
illuminating and it's certainly helped a lot to clarify the issues for me,
Brian.
More information about the Haskell-Cafe
mailing list