map (-2) [1..5]

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
53 messages Options
123
Reply | Threaded
Open this post in threaded view
|

map (-2) [1..5]

Tamas K Papp
The code in the subject generates an error.  I understand why this is
(- is treated as part of the number), but I don't know how to solve
it, ie how to tell Haskell that - is a function/binary operator?

Thanks,

Tamas
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

Christian Maeder
 map (\x -> x - 2) [1..5]
or
 map (flip (-) 2) [1..5]

HTH Christian

Tamas K Papp schrieb:
> The code in the subject generates an error.  I understand why this is
> (- is treated as part of the number), but I don't know how to solve
> it, ie how to tell Haskell that - is a function/binary operator?
>
> Thanks,
>
> Tamas
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

Stefan Holdermans
In reply to this post by Tamas K Papp
Tamas,

> The code in the subject generates an error.  I understand why this is
> (- is treated as part of the number), but I don't know how to solve
> it, ie how to tell Haskell that - is a function/binary operator?

What about

   map (flip (-) 2) [1 .. 5]

or

   map (+ (- 2)) [1 .. 5]

?

HTH,

   Stefan
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

David House
In reply to this post by Tamas K Papp
On 17/08/06, Tamas K Papp <[hidden email]> wrote:
> The code in the subject generates an error.  I understand why this is
> (- is treated as part of the number), but I don't know how to solve
> it, ie how to tell Haskell that - is a function/binary operator?

There's a Prelude function for exactly this purpose, which leads your
code still quite readable:

Prelude> map (subtract 2) [1..5]
[-1,0,1,2,3]

--
-David House, [hidden email]
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

Brian Hulley
In reply to this post by Tamas K Papp
Tamas K Papp wrote:
> The code in the subject generates an error.  I understand why this is
> (- is treated as part of the number), but I don't know how to solve
> it, ie how to tell Haskell that - is a function/binary operator?

Actually looking at the Haskell98 report, -2 seems to be treated as (negate
(2)), which I find really strange because there does not appear to be any
way of specifying negative literals, and the range of negative values is
always 1 more than the range of positive values (when you use a fixed
bit-length representation eg Int instead of Integer)

I'd have thought it would have been simpler to just make the rule that -2
(no spaces between '-' and '2') would be a single lexeme, and then people
could just use (negate x) or (0 - x) instead of having a special rule and a
whole lot of confusion just for one arithmetic operator, which is never
actually needed in the first place (just as we don't need /x because it is
simple enough to write 1/x).

I see with great disappointment that Haskell' Trac ticket#50 [1] looks as if
it will not be accepted [2] so we're likely to be stuck with this for years
to come...

[1] http://hackage.haskell.org/trac/haskell-prime/ticket/50
[2] http://hackage.haskell.org/trac/haskell-prime/wiki/StrawPoll-2

So in answer to your question, you can't (except for workarounds already
posted).

Regards, Brian.
--
Logic empowers us and Love gives us purpose.
Yet still phantoms restless for eras long past,
congealed in the present in unthought forms,
strive mightily unseen to destroy us.

http://www.metamilk.com 

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

Stefan Monnier
> I'd have thought it would have been simpler to just make the rule that -2
> (no spaces between '-' and '2') would be a single lexeme,

But then x-2 won't mean "subtract 2 from x" but "call x with arg -2".


        Stefan

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

Jared Updike
In reply to this post by Brian Hulley
> I'd have thought it would have been simpler to just make the rule that -2
> (no spaces between '-' and '2') would be a single lexeme

I'd have thought so too, until I implemented a parser with exponentiation.
It is easy to get confused and make a parser that is too eager to include
the minus sign as part of a numeric literal instead of as subtraction
or unary negation (all you parser-with-exponentiation-implementers out
there, pay attention!). And since many
programming languages (specifically C) don't have syntax for
exponentation as an infix operator (nothing authoritative to copy
precedence from), I had to implement this myself, get confused and see
that it was so---(I tried making the literal include the minus sign if
there was no space). I never noticed this before because in a C-like
language:

-4*2    is the same whether parsed as

(-4)*2   or  -(4*2)

but

-4^2    is not the same whether parsed as

(-4)^2  or  -(4^2)  (the correct version)

Basically, before someone argues this with me,

-4^2 should parse the same as

- 4^2 which should be the same thing as

0 - 4^2

(you don't want -4^2  and 0-4^2 giving different results, no matter
how much you think whitespace belongs around operators)

Math follows these same rules but it's slightly harder to get confused
because of the way exponentiation is written by superscripting. See
http://mathforum.org/library/drmath/view/55709.html and
http://mathforum.org/library/drmath/view/53240.html.

I thought this was surprising, that parsing the minus sign into
lexemes would cause such confusion, but it is born out in many places
(Python, Frink (http://futureboy.homeip.net/frinkdocs/FrinkApplet.html),
etc.)

(Note: this email isn't about Haskell specifically and I'm sure issues
with the minus sign in Haskell are more confusing than this; this is
purely about parsing a C-like langauge extended with exponentionation
and how including the minus sign in the literal is dangerous in
conjuntion with exponentiation.)

  Jared.
--
http://www.updike.org/~jared/
reverse ")-:"
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

Jon Fairbairn
In reply to this post by Stefan Monnier
Stefan Monnier <[hidden email]> writes:

> > I'd have thought it would have been simpler to just make the rule that -2
> > (no spaces between '-' and '2') would be a single lexeme,
>
> But then x-2 won't mean "subtract 2 from x" but "call x with arg -2".

Well, since the normal typographical convention is that
"hyphenated-words" are read as closely connected, I've
always been in favour of including hyphen in variable names
and using spaces to separate them from tokens, so perhaps it
should just mean "the identifier 'x-2'".

Though in the days of Unicode we could get round the whole
thing by using code 0x002d for unary minus, 0x2010 in
identifiers and 0x2212 for infix minus... and spend many a
happy hour trying to tell which of the three was intended by
some short horizontal line.

--
Jón Fairbairn                                 [hidden email]
http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html  (updated 2006-07-14)

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

John Meacham
In reply to this post by Brian Hulley
On Thu, Aug 17, 2006 at 11:14:32AM +0100, Brian Hulley wrote:
> I'd have thought it would have been simpler to just make the rule that -2
> (no spaces between '-' and '2') would be a single lexeme, and then people
> could just use (negate x) or (0 - x) instead of having a special rule and a
> whole lot of confusion just for one arithmetic operator, which is never
> actually needed in the first place (just as we don't need /x because it is
> simple enough to write 1/x).

yes yes yes. the current handling of - is a huge wart that needs to be
excised. I run into issues with it still and grumble to myself, and have
been programming haskell for years. '-' should be part of the numerical
lexical syntax and not be special in any other way. we alreday have .
being treated as lexically part of a number, and 'e', and 'x' in certain
cases, so why the special anoying case for '-'?

>
> I see with great disappointment that Haskell' Trac ticket#50 [1] looks as
> if it will not be accepted [2] so we're likely to be stuck with this for
> years to come...
>
> [1] http://hackage.haskell.org/trac/haskell-prime/ticket/50
> [2] http://hackage.haskell.org/trac/haskell-prime/wiki/StrawPoll-2

I hope this changes.


        John

--
John Meacham - ⑆repetae.net⑆john⑈
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: map (-2) [1..5]

John Meacham
In reply to this post by Stefan Monnier
On Thu, Aug 17, 2006 at 11:18:59AM -0400, Stefan Monnier wrote:
> > I'd have thought it would have been simpler to just make the rule that -2
> > (no spaces between '-' and '2') would be a single lexeme,
>
> But then x-2 won't mean "subtract 2 from x" but "call x with arg -2".

but now at least a highlighting editor can tell the difference and
highlight '-2' as a number and x as a variable. I mean,

0x22 does not mean the same thing as 0 x 32 or 0.32 or 0 . 32.

we already have special lexical rules for numbers and no one has
complained about any of them. but issues with  the '-' handling come up
quite regularly.

        John

--
John Meacham - ⑆repetae.net⑆john⑈
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

Brian Hulley
In reply to this post by Jared Updike
Jared Updike wrote:

> -4^2    is not the same whether parsed as
>
> (-4)^2  or  -(4^2)  (the correct version)
>
> Basically, before someone argues this with me,
>
> -4^2 should parse the same as
>
> - 4^2 which should be the same thing as
>
> 0 - 4^2

I'd argue that -4^2 should parse as (-4)^2 in the same way that:

    f x `op` y    ===  (f x) `op` y

I'd also argue that in maths the necessary brackets are implied by the
superscripting syntax, and for programming, as long as the editor does basic
highlighting of literals it would be very clear that -4 is a single lexeme.

Stefan Monnier wrote:
>> I'd have thought it would have been simpler to just make the rule
>> that -2 (no spaces between '-' and '2') would be a single lexeme,
>
> But then x-2 won't mean "subtract 2 from x" but "call x with arg -2".

Literal highlighting in the editor would make it clear that x-2 === x (-2).
I think a basic issue is that at the moment it is strange that non-negative
numbers can be specified as literals but negative numbers can't - they can
only get in through the "back door" of evaluation - which just doesn't seem
right.

It's kind of like a Monty Python'esque sketch of a lecture theatre full of
mathematicians where every attempt to mention a negative number is replaced
by the word "apple"... ;-)

Regards, Brian.

--
Logic empowers us and Love gives us purpose.
Yet still phantoms restless for eras long past,
congealed in the present in unthought forms,
strive mightily unseen to destroy us.

http://www.metamilk.com 

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

David House
On 17/08/06, Brian Hulley <[hidden email]> wrote:
> Literal highlighting in the editor would make it clear that x-2 === x (-2).
> I think a basic issue is that at the moment it is strange that non-negative
> numbers can be specified as literals but negative numbers can't - they can
> only get in through the "back door" of evaluation - which just doesn't seem
> right.

You also can't specify string literals: they're sugar for
'a':'b':'c':[]. You seem to be arguing that syntactic sugar, and by
extension, a small core language, is bad.

--
-David House, [hidden email]
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

Jared Updike
In reply to this post by Brian Hulley
> I'd also argue that in maths the necessary brackets are implied by the
> superscripting syntax

ASCII text parsing issues aside, in math,

    2
-4           =    ?

(No you cannot ask if there is space between the 4 and the - symbol,
or if I "meant" (-4)^2   or -(4^2), or if I wrote a negative sign or a
subtract sign. I believe there is only one standard interpretation
here.)

> they can only get in through the "back door" of evaluation
> which just doesn't seem right.

Constant folding can eliminate any runtime cost, so effectively 0 - 2
==> negative 2 at compile time. No problem.

  Jared

--
http://www.updike.org/~jared/
reverse ")-:"
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

John Meacham
In reply to this post by David House
On Thu, Aug 17, 2006 at 09:17:39PM +0100, David House wrote:

> On 17/08/06, Brian Hulley <[hidden email]> wrote:
> >Literal highlighting in the editor would make it clear that x-2 === x (-2).
> >I think a basic issue is that at the moment it is strange that non-negative
> >numbers can be specified as literals but negative numbers can't - they can
> >only get in through the "back door" of evaluation - which just doesn't seem
> >right.
>
> You also can't specify string literals: they're sugar for
> 'a':'b':'c':[]. You seem to be arguing that syntactic sugar, and by
> extension, a small core language, is bad.

No, I think he is saying this particular piece of syntactic sugar is more
like syntactic castor oil. Also, the main reason it needed to be
"special" was not for terms, but for n+k patterns, where you couldn't
use 'negate' and have it parse properly. but n+k patterns are likely to
be dropped anyway so we might as well do away with this subwart too.

        John

--
John Meacham - ⑆repetae.net⑆john⑈
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

Brian Hulley
In reply to this post by Jared Updike
Jared Updike wrote:

>> I'd also argue that in maths the necessary brackets are implied by
>> the superscripting syntax
>
> ASCII text parsing issues aside, in math,
>
>    2
> -4           =    ?
>
> (No you cannot ask if there is space between the 4 and the - symbol,
> or if I "meant" (-4)^2   or -(4^2), or if I wrote a negative sign or a
> subtract sign. I believe there is only one standard interpretation
> here.)

Yes but my point is that -4^2 is not the same as

                2
            -4

because the latter by convention means - (4^2).

In other words, superscripts bind tighter than prefix ops but prefix ops
bind tighter than infix.

>
>> they can only get in through the "back door" of evaluation
>> which just doesn't seem right.
>
> Constant folding can eliminate any runtime cost, so effectively 0 - 2
> ==> negative 2 at compile time. No problem.

An Int8 has the range -128 to +127 inclusive, so I'd have expected a problem
with the expression

    negate (128 :: Int8)

However I see from
http://en.wikipedia.org/wiki/Two's_complement#The_weird_number that this
works because -128 === +128 ie

               negate (128::Int8)
    ===    negate (-128)    -- literal to typed value
    ===    (+128)              -- negation
    ===    (-128)               -- overflow ignored

Regards, Brian.
--
Logic empowers us and Love gives us purpose.
Yet still phantoms restless for eras long past,
congealed in the present in unthought forms,
strive mightily unseen to destroy us.

http://www.metamilk.com 

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

Brian Hulley
In reply to this post by David House
David House wrote:

> On 17/08/06, Brian Hulley <[hidden email]> wrote:
>> Literal highlighting in the editor would make it clear that x-2 ===
>> x (-2). I think a basic issue is that at the moment it is strange
>> that non-negative numbers can be specified as literals but negative
>> numbers can't - they can only get in through the "back door" of
>> evaluation - which just doesn't seem right.
>
> You also can't specify string literals: they're sugar for
> 'a':'b':'c':[]. You seem to be arguing that syntactic sugar, and by
> extension, a small core language, is bad.

All I'm saying is that given a type, either all the inhabitants should have
a literal form or none of them should, because otherwise the availability of
literals skews one's relationship to the inhabitants.

Ie the lack of negative literals tells me that I should think of negative
integers as being "derived" from positive integers via negation, whereas the
declaration

    data Integer = ... | -1 | 0 | 1 | ...

tells me that the negative and positive integers are on an equal footing.

Ie the language is sending out a "mixed message" about the integers, which
is confusing.

Regards, Brian.
--
Logic empowers us and Love gives us purpose.
Yet still phantoms restless for eras long past,
congealed in the present in unthought forms,
strive mightily unseen to destroy us.

http://www.metamilk.com 

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

Jared Updike
In reply to this post by Brian Hulley
> Yes but my point is that -4^2 is not the same as
>
>                 2
>             -4
>
> because the latter by convention means - (4^2).

> In other words, superscripts bind tighter than prefix ops but prefix ops
> bind tighter than infix.

I see. My point is that there already exists a convention[1] that the
way to type in
   2
-4
is -4^2 which means -(4^2) not (-4)^2 because - as a prefix op has the
same precedence as binary subtraction, not super tight like normal
prefix ops (i.e. normal function application) as you would like it to
be (if I understand correctly). You are welcome to break an existing
(unofficial) convention for the sake of lexical syntax[2].

Cheers,
  Jared.

[1] On my TI89 calculator (where there are even two - buttons: a
little "negative unary" button and a "binary subtract" button). It
pretty prints
   2
-4     =  -16
when I punch in -4^2  (where - is the "negative unary" button). The
answer is -16. Python (-4**2 = -4 ** 2 = - 4 ** 2 = -16) and Matlab
and Mathematica agree (-4^2 = -4 ^ 2 = - 4 ^ 2 = -16).

[2] http://wadler.blogspot.com/2006/01/bikeshed-coloring.html

--
http://www.updike.org/~jared/
reverse ")-:"
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

John Meacham
In reply to this post by Brian Hulley
On Fri, Aug 18, 2006 at 12:20:54AM +0100, Brian Hulley wrote:
>    data Integer = ... | -1 | 0 | 1 | ...
>
> tells me that the negative and positive integers are on an equal footing.
>
> Ie the language is sending out a "mixed message" about the integers, which
> is confusing.

Not only that but there is a run-time penalty for every polymorphic
negattive literal!

-3 desugars to negate (fromInteger 3)  rather than (fromInteger -3) so
you end up having to do 2 dictionary lookups (one for fromInteger, one
for negate) and indirect function calls rather than just the one.

        John


--
John Meacham - ⑆repetae.net⑆john⑈
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

Brian Hulley
In reply to this post by Jared Updike
Jared Updike wrote:

>> In other words, superscripts bind tighter than prefix ops but prefix
>> ops bind tighter than infix.
>
> I see. My point is that there already exists a convention[1] that the
> way to type in
>        2
>    -4
> is -4^2 which means -(4^2) not (-4)^2 because - as a prefix op has the
> same precedence as binary subtraction, not super tight like normal
> prefix ops (i.e. normal function application) as you would like it to
> be (if I understand correctly). You are welcome to break an existing
> (unofficial) convention for the sake of lexical syntax[2].
> [2] http://wadler.blogspot.com/2006/01/bikeshed-coloring.html

This choice of precedence for unary - conflicts with the normal usage in
languages like C, where unary ops "obviously" bind tighter than infix.

The typesetting in maths conveys a lot of info eg to distinguish f -x from
f - x or f-x, and so the relationship between the visual representation and
the meaning depends on a knowledge of various conventions that have evolved
over time, and the knowledge of when to apply them in a given context.

In contrast, a programming language should be based on general concepts
uniformly applied. In Haskell we have operators, identifiers, prefix
application using an identifier and infix application using a symbol, and a
uniform way to convert a symbol to an identifier and vice versa, and a
uniform way of forming sections.

All this machinery should be enough to be satisfied with. However, someone
somewhere decided that one trivial arithmetic operation, namely unary minus,
should be allowed to totally ruin everything, and not only that, but that
half of any number line, the positives, should (literally!) have a special
advantage over the other half, the negatives.

Thus while I can agree with Wadler that it's easy to have different opinions
on "little" issues, I think that in this case the goal of uniformity leads
to an objective answer.

Of course not all languages care about being uniform or neat ;-)

Best regards, Brian.
--
Logic empowers us and Love gives us purpose.
Yet still phantoms restless for eras long past,
congealed in the present in unthought forms,
strive mightily unseen to destroy us.

http://www.metamilk.com 

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: map (-2) [1..5]

Cale Gibbard
On 17/08/06, Brian Hulley <[hidden email]> wrote:

> Jared Updike wrote:
> >> In other words, superscripts bind tighter than prefix ops but prefix
> >> ops bind tighter than infix.
> >
> > I see. My point is that there already exists a convention[1] that the
> > way to type in
> >        2
> >    -4
> > is -4^2 which means -(4^2) not (-4)^2 because - as a prefix op has the
> > same precedence as binary subtraction, not super tight like normal
> > prefix ops (i.e. normal function application) as you would like it to
> > be (if I understand correctly). You are welcome to break an existing
> > (unofficial) convention for the sake of lexical syntax[2].
> > [2] http://wadler.blogspot.com/2006/01/bikeshed-coloring.html
>
> This choice of precedence for unary - conflicts with the normal usage in
> languages like C, where unary ops "obviously" bind tighter than infix.
>
> The typesetting in maths conveys a lot of info eg to distinguish f -x from
> f - x or f-x, and so the relationship between the visual representation and
> the meaning depends on a knowledge of various conventions that have evolved
> over time, and the knowledge of when to apply them in a given context.
>
> In contrast, a programming language should be based on general concepts
> uniformly applied. In Haskell we have operators, identifiers, prefix
> application using an identifier and infix application using a symbol, and a
> uniform way to convert a symbol to an identifier and vice versa, and a
> uniform way of forming sections.
>
> All this machinery should be enough to be satisfied with. However, someone
> somewhere decided that one trivial arithmetic operation, namely unary minus,
> should be allowed to totally ruin everything, and not only that, but that
> half of any number line, the positives, should (literally!) have a special
> advantage over the other half, the negatives.
>
> Thus while I can agree with Wadler that it's easy to have different opinions
> on "little" issues, I think that in this case the goal of uniformity leads
> to an objective answer.
>
> Of course not all languages care about being uniform or neat ;-)
>
> Best regards, Brian.

First, f - x, f -x, and f-x all tend to mean the same thing in
mathematics, though f -x would be considered poorly typeset (and, to
some degree, they're all poorly typeset, because we're using hyphens
rather than the minus symbol, which really don't look the same). We
tend to write f(-x) when applying a function f to the negation of x,
even in circumstances when application is normally written without
parentheses.

Secondly, I think it's quite a reasonable thing to do to treat unary
negation as a separate operation. It follows quite naturally to do so
from the definition of a ring. While having separate literals for
negative numbers might be okay, it seems unnecessary in light of the
fact that we *do* want a nice looking unary negation symbol, which
doesn't strictly apply to literals. If -x suddenly became a
non-expression, and I had to write 0-x, -1*x or (negate x) instead,
I'd consider that a severe enough bug that I would avoid upgrading my
compiler until it was fixed.

In mathematics, we don't use separate symbols for negative integers,
and negated positive integers, even though in the underlying
representation of the integers as equivalence classes of pairs of
naturals, we can write things like -[(1,0)] = [(0,1)], which expressed
in ordinary notation just says that -1 = -1. This doesn't bother us,
because the two things are always equal.

Another thing to note is that all the natural literals are not, as one
might initially think, plain values, but actually represent the
embedding of that natural number into the ring (instance of Num), by
way of 0 and 1. They simply provide a convenient notation for getting
particular values of many rings, but in many cases, don't get one very
far at all before other functions must be introduced to construct the
constant values one wants. While there always is a homomorphism from Z
to a ring (represented in Haskell by fromInteger), one would get
similar expressiveness by with just the nullary operators 0 and 1, and
the unary negation as well as addition and multiplication (albeit with
an often severe performance hit, and some annoyance, I'm not
recommending we really do this, simply characterising the purpose of
numeric literals).

If the performance issue regarding the polymorphic literal -5 meaning
negate (fromInteger 5) is a problem, it would be easy enough to agree
for the compiler to find and rewrite literals like that as fromInteger
(-5) instead, where -5 is the precomputed integer -5. Assuming that
fromInteger is not broken, that will always mean the same thing
(because fromInteger is supposed to be a homomorphism). Similarly,
when the type of (fromInteger x) is known statically to be Integer,
the compiler can rewrite it as x. In any event, this is a tiny
constant factor performance hit.

Anyway, the point of all this is that 0,1,2... are not really literals
at all. They're nullary operators which give particular elements of
any given instance of Num. Perhaps at some level in the compiler after
performing the fromInteger transformation they may be taken as literal
integers, but there is no reason that this level has to be exposed to
the user.

Additionally, consider things like Rational. It is possible to write
some elements of Rational in terms of integer "literals", but not all
of them, even if negative literals become included. Floating point
literals help a bit here, but not really all that much. (Consider
things like 1/3, or 1/7.) In particular, any rational number with a
denominator greater than 1 is inaccessible from that interface. Based
on your previously mentioned design principle that all values of a
type should be expressible via literals, or none of them should be, we
should in fact remove the polymorphic interface for 0,1, etc. and
force the user to type 1%1 for the rational 1. But this is annoying,
and destroys polymorphism!

I think that design principle is broken. If it was extended to say
something like "All values of a type should be possible to write
solely in terms of its constructors, or none of them should be.", then
potentially infinite data structures would be excluded from having
exposed constructors, for no good reason other than that there are
infinite values which require other operations to define. This is, in
a way, rather similar to the problem with rationals.

I'd also like to say that the exponentiation example is also a good
one. -4^2 is *always* -16, in every sane mathematical context since
unary negation is treated as an additive operation, and thus should
happen after exponentiation and multiplication (though under normal
circumstances, it doesn't matter whether it's done before or after
multiplication).

Though this is a little offtopic, another important thing to note
about parsing exponentiation is that a^b^c always means a^(b^c) and
not (a^b)^c, which is a fairly standard thing in mathematics, because
of the tendency to automatically rewrite (a^b)^c as a^(b*c), which
looks nicer (and wouldn't normally involve parentheses on the page),
and that no such rule exists for the other association.

While I've considered that there are reasons that requiring spaces to
be included to separate operator symbols from their arguments might
actually be a decent thing to have, I wouldn't recommend doing things
in the way that you're suggesting. With that in place, we could have
negative integer literals (provided that people really care that
strongly), but that's no reason to drop unary negation altogether --
just require that a space occur between the unary minus and its
parameter. However, there are certain operators, especially
exponentiation, and multiplication inside an additive expression,
which putting spaces around them just looks "wrong" to me, and though
I might be able to get used to it, I'd probably end up recompiling
things all the time over syntax errors related to it. Newcomers to the
language would also probably dislike it when they typed x+y at the
ghci prompt and got some error saying that x+y is not in scope.

 - Cale
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
123