[Haskell-cafe] Re: map (-2) [1..5]
On 2006-09-11, Aaron Denney <[EMAIL PROTECTED]> wrote: >> See "What About the Natural Numbers" - "Colin Runciman" - it's a good read :) > > I will when I get the chance. Finally found a copy. It is a good read. I mostly agree with him. The biggest exception is about the need for highly optimized, near the machine level, representations of the naturals. 17 years later with much better computers, I think the unary representation works just fine, and transparently conveys what it means. -- Aaron Denney -><- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
On 2006-09-11, Henning Thielemann <[EMAIL PROTECTED]> wrote: > > On Sun, 10 Sep 2006, Aaron Denney wrote: > >> >> Of course, there's always a typeclass, where we could add all sorts of >> >> other encodings of the Peano axioms, such as binary trees,, but I don't >> >> see that that buys us much if we don't also get access to operations >> >> beyond them, such as (an _efficient_) `div` for fastexp. >> > >> > I don't see why Natural can't have an instance of whatever >> > class ends up owning "div". It's perfectly well behaved on >> > Naturals. >> >> True. It seems odd to have a multiplicative (pseudo) inverse, but >> not an additive, though. Breaking up the numeric hierarchy too finely >> seems like it would be a pain -- take it to the limit of a >> separate class per function. What else would you drag in with "div"? >> "mod", (*), ...? > > > from http://darcs.haskell.org/numericprelude/src/Algebra/Core.lhs : > >> class (Num a) => Integral a where >> div, mod :: a -> a -> a >> divMod :: a -> a -> (a,a) >> >> -- Minimal definition: divMod or (div and mod) >> div a b = fst (divMod a b) >> mod a b = snd (divMod a b) >> divMod a b = (div a b, mod a b) That particular division means that Naturals can't support div because they're not a ring, which the (Num a) in that snippet above means for this numeric hierarcy, right? So this does drag in div, mod and (*), which all seem mostly reasonable, but it also drags in (-) and "negate", which you don't want for Naturals. -- Aaron Denney -><- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
On 2006-09-11, Simon Peyton-Jones <[EMAIL PROTECTED]> wrote: >| Well, it seems a shame that we don't have postfix operators already. > > Actually, the up-coming GHC 6.6 does allow this. Awesome. -- Aaron Denney -><- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
On 2006-09-10, Neil Mitchell <[EMAIL PROTECTED]> wrote: > Hi, > >> I think in practice this wouldn't really be an issue. When you're >> using natural numbers, you tend to be in a situation where you're >> either numbering things statically, and not doing any calculations >> with them, or you're using them as a monoid, whereby things only >> increase. > > take? primes? fibs? ackermanns? take is more an iteration than a numerical calculation -- it works best as pattern matching on Succ and Zero. Primes and fibs are purely generative streams that can be calculated just fine using integers. If you want to geta specific value out, then sure, index using naturals, which again is a data-structural induction. Yes, it's nice to be able to encode the invariant "x > 0". It'd also be nice to be able to encode invariants like (x > 10), or (a < x < b) for array access. But for both of these it is more natural to work with a subset of the integers, than a new type. Yes, even if this means dealing with partial functions. And, as I pointed out before, if naturals are represented asunary, then it means you can do "take infinity xs where infinity = Succ infinity" > See "What About the Natural Numbers" - "Colin Runciman" - it's a good read :) I will when I get the chance. -- Aaron Denney -><- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: map (-2) [1..5]
On Sun, 10 Sep 2006, Aaron Denney wrote: > >> Of course, there's always a typeclass, where we could add all sorts of > >> other encodings of the Peano axioms, such as binary trees,, but I don't > >> see that that buys us much if we don't also get access to operations > >> beyond them, such as (an _efficient_) `div` for fastexp. > > > > I don't see why Natural can't have an instance of whatever > > class ends up owning âdivâ. It's perfectly well behaved on > > Naturals. > > True. It seems odd to have a multiplicative (pseudo) inverse, but > not an additive, though. Breaking up the numeric hierarchy too finely > seems like it would be a pain -- take it to the limit of a > separate class per function. What else would you drag in with "div"? > "mod", (*), ...? from http://darcs.haskell.org/numericprelude/src/Algebra/Core.lhs : > class (Num a) => Integral a where > div, mod :: a -> a -> a > divMod :: a -> a -> (a,a) > > -- Minimal definition: divMod or (div and mod) > div a b = fst (divMod a b) > mod a b = snd (divMod a b) > divMod a b = (div a b, mod a b) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Re: map (-2) [1..5]
| Well, it seems a shame that we don't have postfix operators already. | I guess that means I am arguing we should introduce a unary postfix | operator, and not even have sugar for factorial, as it conflicts with | array access. | | We *almost* do: | Hugs.Base> let (!) 0 = 1; (!) x = x*((!) (x-1)) in (5 !) | Sadly, | Prelude> let (!) 0 = 1; (!) x = x*((!) (x-1)) in (5 !) Actually, the up-coming GHC 6.6 does allow this. Some while ago I made the type checker a tiny bit more lenient about left sections, so that (x !) would typecheck iff ((!) x) typechecks. (Strictly, Haskell 98 requires that the section typechecks iff (\y. (!) x y) typechecks, and I should really have made the relaxation dependent on a flag, but I didn't.) Anyway, you get postfix operators. I'd better document this. Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: map (-2) [1..5]
See also: torsors http://math.ucr.edu/home/baez/torsors.html Jim ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: map (-2) [1..5]
Hi, I think in practice this wouldn't really be an issue. When you're using natural numbers, you tend to be in a situation where you're either numbering things statically, and not doing any calculations with them, or you're using them as a monoid, whereby things only increase. take? primes? fibs? ackermanns? There are lots of things things were computation is performed on natural numbers, in fact, I'd say its relatively rare to find negative integers! See "What About the Natural Numbers" - "Colin Runciman" - it's a good read :) Thanks Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: map (-2) [1..5]
On 10/09/06, Aaron Denney <[EMAIL PROTECTED]> wrote: I still don't like having a plus without a minus. I think in practice this wouldn't really be an issue. When you're using natural numbers, you tend to be in a situation where you're either numbering things statically, and not doing any calculations with them, or you're using them as a monoid, whereby things only increase. -- -David House, [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
On 2006-09-09, Jón Fairbairn <[EMAIL PROTECTED]> wrote: > Aaron Denney <[EMAIL PROTECTED]> writes: >> Meh. Naturals are reasonably useful sometimes, but not often enough, in >> my opinion. Any sort of numeric hierarchy designed to deal with them >> would be totally broken from my point of view -- if you don't at least >> have inverses, it's not a number, > > Crikey. Would you really have me accept that the natural > numbers aren't numbers? I'd like it if you would, but don't expect to convince you. >> just some sort of weird algebraic structure. And if it's >> not in the numeric hierarchy, and so you can't do >> arithmetic syntactically nicely with it, what's the point? > > Could you elaborate? I haven't thought it through, but I > can't see why splitting Num into something that puts Natural > "above" Integer would be particularly problematic. For a Natural typeclass to be useful in keeping full-blown Integers away from functions like "take", it can't be above the ones Integer belongs to. Instead it has to "hang off the side" of the numeric hierarchy. You can split this into a "tagging" class on the side and what naturals and integer have in common. Or, of course, you could onry allow one implementation of naturals, and have the Natural typeclass not used to enforce these restriction, but just the data type itself. > Natural just has fewer operations than Integer. It doesn't have > â-â, but it does have âdifference:: Natural -> Natural -> > Naturalâ, and so do the bigger types (âdifference a b = abs (a - > b)â) Is difference ever a useful function? I guess I don't see it as terribly natural. Placing it in the hierarchy somewhere above the class with (-) also means we can't have a default definition in terms of (-). >> Is it better to make (^^), (^), and "take" partial functions, or to make (-) >> and "negate" partial functions? > > No :-). â-â and ânegateâ would belong to a class of which > Natural had no instances. That could work. I still don't like having a plus without a minus. >> Of course, there's always a typeclass, where we could add all sorts of >> other encodings of the Peano axioms, such as binary trees,, but I don't >> see that that buys us much if we don't also get access to operations >> beyond them, such as (an _efficient_) `div` for fastexp. > > I don't see why Natural can't have an instance of whatever > class ends up owning âdivâ. It's perfectly well behaved on > Naturals. True. It seems odd to have a multiplicative (pseudo) inverse, but not an additive, though. Breaking up the numeric hierarchy too finely seems like it would be a pain -- take it to the limit of a separate class per function. What else would you drag in with "div"? "mod", (*), ...? I was thinking of useful implementations solely in terms of the Peano-axiom interface, which only really needs to be there for a default implementation. -- Aaron Denney -><- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: map (-2) [1..5]
Jón Fairbairn wrote: "Brian Hulley" <[EMAIL PROTECTED]> writes: I imagine that almost every editor at least does lexical fontification, and if so, then I don't think there could be much confusion in practice between these uses of '-'. I think that unnecessarily disadvantages people with poorer than average (including zero) eyesight. For people lacking good eyesight the equivalent of fontification could simply be some text-to-speech system which read "-2" as "negative 2" and "x - y" as "x minus y". Yes, a typeclass for exp would be ideal Well, so long as you call it “exponent” or “expt”. I'd completely forgotten about the normal (exp) function. I should have written (power) or (pow), though as Cale pointed out a typeclass may not be a suitable solution due to the lack of a functional dependency to help the compiler choose the correct overloading. - in that case I'd go back to advocating (powNat) (powInt) etc. (and a newtype for Natural). Here's a design principle for you: if an error can be detected at compile time, it should be. If we have literals for naturals and not negative integers, “negate 100” causes no problem, it just means “negate (fromNatural 100)”. If we have literals for integers and try to restrict them to get naturals, “-100:: Natural” becomes shorthand for “integralToNatural (-100)”, and would (in the absence of somewhat arbitrary special-casing in the compiler) give a runtime error. Ok I'm slowly coming round to the view that having negative literals is not ideal. I also agree with Tamas's suggestion that an empirical analysis of Haskell source code could be useful to determine the practical implications of unary minus, It has merit and I would laud anyone who got round to doing it, but there's a danger of measuring the wrong thing. What we want to know is not what is more frequent, but what causes the greater number of misreadings and which pieces of code had the most syntax errors before they were completed, and that's harder to measure. Though if unary minus turned out to be very rare, we could just drop it. Using “(0-)” wouldn't be much of a hardship in that case. Anyway no doubt I've posted enough emails about unary minus and negative literals so I'll be quiet now ;-) :-) ... ? I think the main problem with unary negation is that it's the only place in Haskell where the same symbol is being used to represent two different (ie not overloads of each other) functions. I can see why people were tempted to do this, because there is such an intimate relationship between unary minus and binary subtraction. However I feel it is a slippery slope: convenience has been put before uniformity leading to confusion. While such things might be justified in a domain specific language like mathematica or matlab, for a general purpose language like Haskell it seems less reasonable to make an exception just for one arithmetic function. 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 Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
"Brian Hulley" <[EMAIL PROTECTED]> writes: > Jón Fairbairn wrote: > > [1] “-” is a varsym. The logical way of achieving what you > > suggest (ie -1 -2... as constructors for Integer) would be > > to make it introduce a consym the way “:” does, but then it > > couldn't be an infix operator anymore. > > I don't think it's necessary to use the same kind of rule > for '-' as for ':'. Not necessary, but you surely don't want yet another rule? > I imagine that almost every editor at least does lexical > fontification, and if so, then I don't think there could be > much confusion in practice between these uses of '-'. I think that unnecessarily disadvantages people with poorer than average (including zero) eyesight. > Yes, a typeclass for exp would be ideal Well, so long as you call it “exponent” or “expt”. > (and a newtype for Natural). Here's a design principle for you: if an error can be detected at compile time, it should be. If we have literals for naturals and not negative integers, “negate 100” causes no problem, it just means “negate (fromNatural 100)”. If we have literals for integers and try to restrict them to get naturals, “-100:: Natural” becomes shorthand for “integralToNatural (-100)”, and would (in the absence of somewhat arbitrary special-casing in the compiler) give a runtime error. > I also agree with Tamas's suggestion that an empirical > analysis of Haskell source code could be useful to determine > the practical implications of unary minus, It has merit and I would laud anyone who got round to doing it, but there's a danger of measuring the wrong thing. What we want to know is not what is more frequent, but what causes the greater number of misreadings and which pieces of code had the most syntax errors before they were completed, and that's harder to measure. Though if unary minus turned out to be very rare, we could just drop it. Using “(0-)” wouldn't be much of a hardship in that case. > Anyway no doubt I've posted enough emails about unary minus > and negative literals so I'll be quiet now ;-) :-) ... ? -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
Aaron Denney <[EMAIL PROTECTED]> writes: > On 2006-09-08, Jón Fairbairn <[EMAIL PROTECTED]> wrote: > > Why shouldn't Naturals be more primitive than Integers? > > Certainly they're more primitive. Too primitive to have reasonable > algebraic properties. Hmph. Naturals obey (a+b)+c == a+(b+c), which is a nice and reasonable algebraic property that Float and Double don't obey. In fact Float and Double have lots of /un/reasonable algebraic properties, but we still have them in the language. (I think they should be turfed out into a numerical library). -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-07) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
Aaron Denney <[EMAIL PROTECTED]> writes: > Jón Fairbairn <[EMAIL PROTECTED]> wrote: > > I think the present design is wrong because we don't have a > > type for naturals. > > Meh. Naturals are reasonably useful sometimes, but not often enough, in > my opinion. Any sort of numeric hierarchy designed to deal with them > would be totally broken from my point of view -- if you don't at least > have inverses, it's not a number, Crikey. Would you really have me accept that the natural numbers aren't numbers? > just some sort of weird algebraic structure. And if it's > not in the numeric hierarchy, and so you can't do > arithmetic syntactically nicely with it, what's the point? Could you elaborate? I haven't thought it through, but I can't see why splitting Num into something that puts Natural "above" Integer would be particularly problematic. Natural just has fewer operations than Integer. It doesn't have “-”, but it does have “difference:: Natural -> Natural -> Natural”, and so do the bigger types (“difference a b = abs (a - b)”) > Is it better to make (^^), (^), and "take" partial functions, or to make (-) > and "negate" partial functions? No :-). “-” and “negate” would belong to a class of which Natural had no instances. If you're the sort of person who likes having partial functions like “head” sullying the scene, you might find it convenient to have “integralToNatural” that either returns the corresponding Natural or throws an exception. Actually, if you are someone like that, you probably want to give it a shorter name... > Of course, there's always a typeclass, where we could add all sorts of > other encodings of the Peano axioms, such as binary trees,, but I don't > see that that buys us much if we don't also get access to operations > beyond them, such as (an _efficient_) `div` for fastexp. I don't see why Natural can't have an instance of whatever class ends up owning “div”. It's perfectly well behaved on Naturals. -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-07) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
Aaron Denney <[EMAIL PROTECTED]> writes: > We already have this great syntax, parsing semanticsi for precedence, > and so forth for declaring infix operators. Couldn't we add to that > slightly by declaring postfix operators as well? Actually, declaring a > unary operator infix yielding a postfix operator doesn't seem like too > much abuse. Possibly not, provided they're always used as sections. (e #) already always means "supply e as the first argument to (#)"). > (I haven't thought this through to any great extent. How much would it > complicate parsing? Not much, I would assume, as this fails in ghc at > the type-checking stage.) I don't think it would complicate mechanical parsing unreasonably. I do think (if done without the parentheses) it might complicate /human/ parsing unreasonably. -- Jón Fairbairn [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-09-07) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
On 2006-09-08, Brian Hulley <[EMAIL PROTECTED]> wrote: > Leaving aside the question of negative literals for the moment, what's so > special about unary minus that it warrants a special syntax? For example in > mathematics we have x! to represent (factorial x), which is also an > important function, yet no-one is arguing that we should introduce a unary > postfix operator to Haskell just to support it. Well, it seems a shame that we don't have postfix operators already. I guess that means I am arguing we should introduce a unary postfix operator, and not even have sugar for factorial, as it conflicts with array access. We *almost* do: Hugs.Base> let (!) 0 = 1; (!) x = x*((!) (x-1)) in (5 !) Sadly, Prelude> let (!) 0 = 1; (!) x = x*((!) (x-1)) in (5 !) :1:41: No instance for (Num (t -> t1)) arising from the literal `5' at :1:41 Probable fix: add an instance declaration for (Num (t -> t1)) In the first argument of `(!)', namely `5' In the definition of `it': it = let ! 0 = ... ! x = ... in (5 !) And hugs doesn't work with out the parentheses in the expression. We already have this great syntax, parsing semanticsi for precedence, and so forth for declaring infix operators. Couldn't we add to that slightly by declaring postfix operators as well? Actually, declaring a unary operator infix yielding a postfix operator doesn't seem like too much abuse. I could have sworn I'd seen ternary operators the same way, but > ((id) `either` (id) (Left 5)) doesn't appear to work. Then there's also the infix data constructors for postfix... Okay, that's complicated because of lack of precedence, but surely that just means extra parentheses? (I haven't thought this through to any great extent. How much would it complicate parsing? Not much, I would assume, as this fails in ghc at the type-checking stage.) (Tounge only *half* in cheek.) -- Aaron Denney -><- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
On 2006-09-08, Jón Fairbairn <[EMAIL PROTECTED]> wrote: > "Brian Hulley" <[EMAIL PROTECTED]> writes: >> In the context of programming, I don't see the problem of >> just thinking of the integers as a primitive built-in data >> type which contains some range of positive and negative >> integers which I'd argue should all be treated on an equal >> footing when the context of discourse is the integers not >> the naturals. > > I'm not sure what that means. Why should they be equal? Why > shouldn't Naturals be more primitive than Integers? Certainly they're more primitive. Too primitive to have reasonable algebraic properties. >> I don't think there is a need to force spaces to be put >> around every infix application. It's only when there would >> be a conflict with the lexical syntax that spaces are >> needed, just as at the moment we have (F . G) versus (F.G), >> (f $ g) versus (f $g) etc. > > That rather goes against your simplicity of design argument, > doesn't it? Why the special cases? For years I've been > rather sloppy about spaces around â$â, and now when I use > template haskell, this bites me. At some point in the > future someone might decide that & or % is needed to > introduce a new chunk of syntax, and formerly valid > programmes break. So why not just say that varsym varid is > in general reserved for future special syntaxes, and require > varsym whitespace varid everywhere? Hmm. Quite reasonable, actually, if we were designing the language de novo. And easily enough to write correctors for current code. -- Aaron Denney -><- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
"Cale Gibbard" <[EMAIL PROTECTED]> writes: > 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. Excellent point, and good categorical thinking. The morphisms are more important than the objects. Jón Fairbairn <[EMAIL PROTECTED]> wrote: > I think the present design is wrong because we don't have a > type for naturals. Meh. Naturals are reasonably useful sometimes, but not often enough, in my opinion. Any sort of numeric hierarchy designed to deal with them would be totally broken from my point of view -- if you don't at least have inverses, it's not a number, just some sort of weird algebraic structure. And if it's not in the numeric hierarchy, and so you can't do arithmetic syntactically nicely with it, what's the point? Is it better to make (^^), (^), and "take" partial functions, or to make (-) and "negate" partial functions? Hmm, here's an idea: have a Nat type, but no arithmetic defined on it besides Succ, and isZero. Of course, that makes the fastexp algorithm unfeasible, and is essentially isomorphic to [()]. Hmm. That gives > length = map (const ()) > take = zipWith (flip const) Feel free to consider this a strawman, but it *is* kind of elegant. There's no scaling loss, as these are inherently O(N). And it even means length and take can handle infinite lists. What's not to like? Of course, there's always a typeclass, where we could add all sorts of other encodings of the Peano axioms, such as binary trees,, but I don't see that that buys us much if we don't also get access to operations beyond them, such as (an _efficient_) `div` for fastexp. (Taking every n'th element (Peano encoded, of course) is _not_ good enough). -- Aaron Denney -><- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: map (-2) [1..5]
On Sat, Sep 09, 2006 at 12:57:56AM -0400, Cale Gibbard wrote: > Num itself needs to be split, but we can't do it sanely without > something like class aliases. I think that a finer grain numeric hierarchy, while retaining Num, etc, is feasible without changing the language: unlike the case of monads, the people who will be defining instances of numeric classes are the very ones who are inconvenienced by the current hierarchy. The main impact on clients of the classes is that some functions would have more general types. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: map (-2) [1..5]
On 09/09/06, Cale Gibbard <[EMAIL PROTECTED]> wrote: When I first ran into the problem with (-) and sections, I was slightly annoyed with having to write (+ (-1)) Let's not forget that there is the library function 'subtract' for this purpose. What you wrote could be written as (subtract 1), which is more readable in my opinion. But hey, what do I know, I think using the underscore for unary negation (à la Emacs calculator) would be an acceptable enough compromise. -- -David House, [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: map (-2) [1..5]
On 08/09/06, Brian Hulley <[EMAIL PROTECTED]> wrote: Jón Fairbairn wrote: > "Brian Hulley" <[EMAIL PROTECTED]> writes: >> Cale Gibbard wrote: >>> 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. >> >> This seems very theoretical to me. > > One of the most valuable aspects of Haskell is it's > theoretical underpinning. Don't play fast and loose with > that! You're right. I should have made a proper argument so here goes: 1) Num a implies that forall a, there is an additive inverse for a (given by (negate)) 2) I think Cale is saying that it is sufficient to have overloaded nullary operators 0 and 1 in conjunction with the (+) and (negate) methods of Num, in order to construct all elements of Num 3) I think also Cale's argument is that the other nullary operators, 2, 3, ... are just there for convenience, but that this convenience is a good thing. So my argument would be that given that we only actually need 0 and 1, but we already have 2, 3,... for convenience, there is no reason to not also have -1, -2, -3, ... as well, for even more convenience, especially as the numeric hierarchy starts with a structure where every element is required to have an additive inverse. My counterargument here is that this doesn't actually increase convenience. In fact, for a lot of reasons, it decreases convenience. > [1] "-" is a varsym. The logical way of achieving what you > suggest (ie -1 -2... as constructors for Integer) would be > to make it introduce a consym the way ":" does, but then it > couldn't be an infix operator anymore. I don't think it's necessary to use the same kind of rule for '-' as for ':'. The rule could be that a '-' immediately followed by a digit starts a negative number, otherwise the '-' is treated as it is at the moment (ie either the start of a comment or a varsym). I imagine that almost every editor at least does lexical fontification, and if so, then I don't think there could be much confusion in practice between these uses of '-'. Also, the fact that we want to allow pattern matching against negative integers suggests that positive integers and negative integers should have equal status regarding literal representation (more precisely: nullary operator overloaded for the integers), rather than having to introduce a special pattern matching rule for the negatives. > Pattern matching on floats is an abomination, definitely a > candidate for removal. Seconded. >> negate (expNat 4 2) >> >> because this would free the ^ symbol for some more widely >> applicable use, and would also make the particular choice of >> exponentiation operator more explicit > > Agreed, though I'd want expt to be part of a typeclass > (possibly multi-parameter to get exp:: Integral a => a -> > Natural -> a as an instance?). Yes, a typeclass for exp would be ideal (and a newtype for Natural). Num itself needs to be split, but we can't do it sanely without something like class aliases. I actually think that the (^), (^^), (**) distinction is rather refreshing to see in a programming language. Most languages don't take the care to distinguish that there are actually different levels of definition of exponentiation. You can't just merge them -- have you looked at their types? (^^) can't be defined for Integers, but it works fine for Rational bases, (**) can't be defined for Rational bases, but works fine for floating point. Additionally, these operations have different performance and numerical properties. If we have a typeclass for this, it will be multiparameter, and there will not be a functional dependency. This could create additional annoyance in various situations. In mathematics, these operations are given the same notation, but are definitely distinguished between by the humans using them. Perhaps we could even use (neg) instead of (negate) in deference to the 3 letter varids used for other common arithmetic ops, to get: neg (exp 4 2) neg y * 56 ("neg" can also be read declaratively as "negative", instead of the imperative "negate".) I obviously already disagree with this whole bit anyway, but eek, don't steal exp. We already have a very important function (in fact, I'd be willing to say that it's probably the most important function in all of mathematics) called exp, and it's named after its standard name in mathematics. Also, not using infix notation for exponentiation would obfuscate many simple mathematical programs. Anything involving a polynomial will look terrible. (I don't care if you're a C programmer and you're used to polynomials looking terrible, I'm not.) I don't really care too much either way with negate <-> neg, I know some people hate ab
Re: [Haskell-cafe] Re: map (-2) [1..5]
Jón Fairbairn wrote: "Brian Hulley" <[EMAIL PROTECTED]> writes: Cale Gibbard wrote: 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. This seems very theoretical to me. One of the most valuable aspects of Haskell is it's theoretical underpinning. Don't play fast and loose with that! You're right. I should have made a proper argument so here goes: 1) Num a implies that forall a, there is an additive inverse for a (given by (negate)) 2) I think Cale is saying that it is sufficient to have overloaded nullary operators 0 and 1 in conjunction with the (+) and (negate) methods of Num, in order to construct all elements of Num 3) I think also Cale's argument is that the other nullary operators, 2, 3, ... are just there for convenience, but that this convenience is a good thing. So my argument would be that given that we only actually need 0 and 1, but we already have 2, 3,... for convenience, there is no reason to not also have -1, -2, -3, ... as well, for even more convenience, especially as the numeric hierarchy starts with a structure where every element is required to have an additive inverse. [1] “-” is a varsym. The logical way of achieving what you suggest (ie -1 -2... as constructors for Integer) would be to make it introduce a consym the way “:” does, but then it couldn't be an infix operator anymore. I don't think it's necessary to use the same kind of rule for '-' as for ':'. The rule could be that a '-' immediately followed by a digit starts a negative number, otherwise the '-' is treated as it is at the moment (ie either the start of a comment or a varsym). I imagine that almost every editor at least does lexical fontification, and if so, then I don't think there could be much confusion in practice between these uses of '-'. Also, the fact that we want to allow pattern matching against negative integers suggests that positive integers and negative integers should have equal status regarding literal representation (more precisely: nullary operator overloaded for the integers), rather than having to introduce a special pattern matching rule for the negatives. Pattern matching on floats is an abomination, definitely a candidate for removal. Seconded. negate (expNat 4 2) because this would free the ^ symbol for some more widely applicable use, and would also make the particular choice of exponentiation operator more explicit Agreed, though I'd want expt to be part of a typeclass (possibly multi-parameter to get exp:: Integral a => a -> Natural -> a as an instance?). Yes, a typeclass for exp would be ideal (and a newtype for Natural). Perhaps we could even use (neg) instead of (negate) in deference to the 3 letter varids used for other common arithmetic ops, to get: neg (exp 4 2) neg y * 56 ("neg" can also be read declaratively as "negative", instead of the imperative "negate".) I don't think there is a need to force spaces to be put around every infix application. It's only when there would be a conflict with the lexical syntax that spaces are needed, just as at the moment we have (F . G) versus (F.G), (f $ g) versus (f $g) etc. That rather goes against your simplicity of design argument, doesn't it? Why the special cases? For years I've been rather sloppy about spaces around “$”, and now when I use template haskell, this bites me. At some point in the future someone might decide that & or % is needed to introduce a new chunk of syntax, and formerly valid programmes break. So why not just say that varsym varid is in general reserved for future special syntaxes, and require varsym whitespace varid everywhere? This would certainly be a simple rule that would also make code easier to read. Summary (imagine the different editor colours/font styles): (- 1) -- a section because of the space (-1) -- a negative number (x - 1) -- (-) x 1 (x -1)-- x applied to (-1) (x -y) -- either (x - y) or, following the above rule, a syntax error. I also agree with Tamas's suggestion that an empirical analysis of Haskell source code could be useful to determine the practical implications of unary minus, which might help to address Jared's comments about the improbability of being able to reach a consensus when everyone has such different experiences/purposes etc. Anyway no doubt I've posted enough emails about unary minus and negative literals so I'll be quiet now ;-) 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.c
[Haskell-cafe] Re: map (-2) [1..5]
"Brian Hulley" <[EMAIL PROTECTED]> writes: > Leaving aside the question of negative literals for the > moment, what's so special about unary minus that it warrants > a special syntax? For example in mathematics we have x! to > represent (factorial x), which is also an important > function, yet no-one is arguing that we should introduce a > unary postfix operator to Haskell just to support it. > > In maths we also have |x| to denote another common function, > (abs x), yet afaia everyone is happy to just write (abs x). That's just a matter of how common the operator is. “-” is so common that if you asked a random passer-by they'd probably identify it correctly, whereas “!” and “|...|” would be likely to elicit a response of "no idea mate". > Would the elimination of the special case rule for unary > minus not make the language easier to understand? A bit, certainly. > What's wrong with typing (negate x) in the rare cases > where you can't just re-write the expression to use infix > minus instead (ie x + -y ===> x - y)? Nothing, really. But in that case, why have a special case for negative literals? “negate 42” would be more consistent¹, and it wouldn't tax language implementors a groat if the language specified that such an application should always be folded into whatever your suggested syntax would have produced. [1] “-” is a varsym. The logical way of achieving what you suggest (ie -1 -2... as constructors for Integer) would be to make it introduce a consym the way “:” does, but then it couldn't be an infix operator anymore. > Surely most programs in Haskell are not just arithmetic > expressions, and while it is convenient to have infix +, > -, *, `div`, `mod` for the integers, so you can do > indexing over data types and other "counting" operations, > I'd argue that the usual functional notation (eg (exp x) > (factorial x) (negate x)) should be sufficient for the > other arithmetic operations just as it's deemed sufficient > for nearly everything else in Haskell! ;-) I can't say that I find anything disagreeable about that suggestion, though the operators aren't on Integers but belong to typeclasses. > > 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. > > This seems very theoretical to me. One of the most valuable aspects of Haskell is it's theoretical underpinning. Don't play fast and loose with that! > In the context of programming, I don't see the problem of > just thinking of the integers as a primitive built-in data > type which contains some range of positive and negative > integers which I'd argue should all be treated on an equal > footing when the context of discourse is the integers not > the naturals. I'm not sure what that means. Why should they be equal? Why shouldn't Naturals be more primitive than Integers? > Another point is that the current treatment requires a > special rule for pattern matching against a negative > integer Perhaps the notional declaration > data Integer = Succ Natural | Zero | Pred Natural (with “Succ 0” meaning 1, of course, possibly with nicer syntax and definitiely with the expectation that it'll be compiled into a decent machine representation) would address that? > or float, Pattern matching on floats is an abomination, definitely a candidate for removal. > > 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). > > In C, it wouldn't be, since there, unary ops always bind > tighter than infix ops, C is almost the last place to look for elegant language design. (Not quite the last, there's Perl and some deliberate gargoyles of languages to go after it) > or better still: > > negate (expNat 4 2) > > because this would free the ^ symbol for some more widely > applicable use, and would also make the particular choice of > exponentiation operator more explicit Agreed, though I'd want expt to be part of a typeclass (possibly multi-parameter to get exp:: Integral a => a -> Natural -> a as an instance?). > I don't think there is a need to force spaces to be put > around every infix application. It's only when there would > be a conflict with the lexical syntax that spaces are > needed, just as at the moment we have (F . G) versus (F.G), > (f $ g) versus (f $g) etc. That rather goes against your simplicity of design argument, doesn't it? Why the special cases? For years I've been rather
[Haskell-cafe] Re: map (-2) [1..5]
"Cale Gibbard" <[EMAIL PROTECTED]> writes: > 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. I wasn't sure where to add this, so here will have to do: I think the present design is wrong because we don't have a type for naturals. So in my view, “-1” should be “negate (fromNatural 1)” -- whatever names we use for those two functions. I can't remember right now why the early versions of Haskell didn't have a Natural type, or what makes it difficult to change to now (and I think this is something we really should do), but even given that, I think the present special casing of “-” is a reasonable compromise. Given a built in Natural type, it makes no sense to have “-” as part of the syntax for literals, since Natural literals don't have it and there's no way to add more constructors (ie negative literals) onto an existing type to get Integer, but having a symbol for negate does it in a straightforward way. * ** * For my own taste, I would have “-” as a character that can appear in identifiers and operators (but special in that if it appears at the beginning it cannot be followed by anything? Otherwise -1 would just be an identifier!) and define > - n = negate n > a +- b = a + (- b) but I think that most people would baulk at having to use “+-” for infix minus. People would similarly baulk at the opposite tack of making “-” solely infix and using something else for negate (as in ML), although finding a different token (such as “__”) for "don't care" and using “_” for unary minus doesn't seem too bad to me. -- Jón Fairbairn [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: map (-2) [1..5]
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 Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
Stefan Monnier <[EMAIL PROTECTED]> 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 [EMAIL PROTECTED] http://www.chaos.org.uk/~jf/Stuff-I-dont-want.html (updated 2006-07-14) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
> 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 Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: map (-2) [1..5]
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 Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe