Brian Hulley | 4 Feb 15:52

Why is $ right associative instead of left associative?

Hi -
In the Haskell98 report section 4.4.2 $ is specified as being right 
associative. This means that f $ a0 a1 $ b0 b1 would parse as f (a0 a1 (b0 
b1)) which seems rather strange to me. Surely it would be much more useful 
if $ were defined as left associative so that it could be used to separate 
the args to f?

Does anyone know why this strange associativity was chosen?

Thanks, Brian.

(The reason I'm asking is that I'm working on the syntax of a language 
similar to Haskell but which uses layout to allow expressions like:

                 f #$                     -- can be followed by an explicit 
block or layout block
                        a0 a1
                        b0 b1

which is sugar for (f $ a0 a1) $ b0 b1 ie f (a0 a1) (b0 b1) ) and I was 
surprised to discover that the parentheses are needed for the most obvious 
reading) 
Ben Rudiak-Gould | 5 Feb 03:27
Picon
Picon
Favicon

Re: Why is $ right associative instead of left associative?

No one has mentioned yet that it's easy to change the associativity of $ 
within a module in Haskell 98:

     import Prelude hiding (($))

     infixl 0 $
     f$x = f x

or, for the purists,

     import Prelude hiding (($))
     import qualified Prelude (($))

     infixl 0 $
     ($) = (Prelude.$)

-- Ben
Tomasz Zielonka | 5 Feb 13:52
Picon

Re: Re: Why is $ right associative instead of left associative?


On Sun, Feb 05, 2006 at 02:27:45AM +0000, Ben Rudiak-Gould wrote: > No one has mentioned yet that it's easy to change the associativity of $ > within a module in Haskell 98: > > import Prelude hiding (($)) > > infixl 0 $ > f$x = f x > > or, for the purists, > > import Prelude hiding (($)) > import qualified Prelude (($)) > > infixl 0 $ > ($) = (Prelude.$)
But that would break Copy & Paste between modules! ;-) Best regards Tomasz -- -- I am searching for programmers who are good at least in (Haskell || ML) && (Linux || FreeBSD || math) for work in Warsaw, Poland
Taral | 4 Feb 20:03
Picon

Re: Why is $ right associative instead of left associative?


On 2/4/06, Brian Hulley <brianh <at> metamilk.com> wrote: > Does anyone know why this strange associativity was chosen?
I think it's very natural. Everything after the $, including other $ expressions, is applied to the stuff before the $. This saves me from a lot of nested parentheses. It seems to be that the left-associative version of $ does not decrease nesting level so effectively. -- Taral <taralx <at> gmail.com> "Computer science is no more about computers than astronomy is about telescopes." -- Edsger Dijkstra
Stefan Holdermans | 4 Feb 20:37
Picon

Re: Why is $ right associative instead of left associative?


Taral wrote: > I think it's very natural. Everything after the $, including other $ > expressions, is applied to the stuff before the $. This saves me from > a lot of nested parentheses.
To me, ($) helping me to avoid writing lots of parentheses, makes it extremely useful. Actually: except for passing function application to higher-order functions, this is the only way I use it. So, I always thought parentheses were *the* reason for the right- associativity of ($). Not sure if it really was originally, but, ever so, I think it is the best reason. Regards, Stefan
Tomasz Zielonka | 4 Feb 20:53
Picon

Re: Why is $ right associative instead of left associative?


On Sat, Feb 04, 2006 at 08:37:51PM +0100, Stefan Holdermans wrote: > Taral wrote: > > >I think it's very natural. Everything after the $, including other $ > >expressions, is applied to the stuff before the $. This saves me from > >a lot of nested parentheses. > > To me, ($) helping me to avoid writing lots of parentheses, makes it > extremely useful. Actually: except for passing function application > to higher-order functions, this is the only way I use it. So, I > always thought parentheses were *the* reason for the right- > associativity of ($). Not sure if it really was originally, but, ever > so, I think it is the best reason.
A left-associative low-precedence application operator can also help avoid writing parentheses, only in different cases, eg. f $$ x + 1 $$ x * x + 2 * x + 1 equals f (x + 1) (x * x + 2 * x + 1) But in this case the parentheses don't nest, which may be a reason why a right-associative version was chosen. ($) helps to avoid the case of nesting parentheses. Such nesting is unbounded, for example you can have chains like this with arbitrary length: a (b (c (d (e (f x))))) even if you only have unary functions. Also, adding or removing a function in such a chain can require non-local changes, that is you are forced to add or remove a closing parenthesis on the end of expression. If you use ($): a $ b $ c $ d $ e $ f x you can easily add or remove a function in the chain. On the other hand, adding new parameters to calls like this f (x + 1) (y - 1) ... is very localised. Best regards Tomasz -- -- I am searching for programmers who are good at least in (Haskell || ML) && (Linux || FreeBSD || math) for work in Warsaw, Poland
Tomasz Zielonka | 4 Feb 16:31
Picon

Re: Why is $ right associative instead of left associative?


On Sat, Feb 04, 2006 at 02:52:20PM -0000, Brian Hulley wrote: > Hi - > In the Haskell98 report section 4.4.2 $ is specified as being right > associative. This means that f $ a0 a1 $ b0 b1 would parse as f (a0 a1 (b0 > b1)) which seems rather strange to me. Surely it would be much more useful > if $ were defined as left associative so that it could be used to separate > the args to f? > > Does anyone know why this strange associativity was chosen?
Probably it was anticipated that right associative version will be more useful. You can use it to create a chain of transformations, similar to a chain of composed functions: (f . g . h) x = f $ g $ h $ x Example: map f $ group $ sort $ filter g $ l But of course, left associative version can also be useful. Some time ago I used a left associative version of the strict application operator, which I named (!$). Anyway, you can't always remove all parentheses. And why would you want to? Everybody is used to them. Best regards Tomasz -- -- I am searching for programmers who are good at least in (Haskell || ML) && (Linux || FreeBSD || math) for work in Warsaw, Poland
ajb | 5 Feb 01:02
Favicon
Gravatar

Re: Why is $ right associative instead of left associative?

G'day all.

Quoting Tomasz Zielonka <tomasz.zielonka <at> gmail.com>:

> Probably it was anticipated that right associative version will
> be more useful. You can use it to create a chain of transformations,
> similar to a chain of composed functions:
>
>     (f . g . h) x   =   f $ g $ h $ x

Of course, if $ were left-associative, it would be no less useful here,
because you could express this chain thusly:

    f . g . h $ x

This is the way that I normally express it.  Partly because I find
function application FAR more natural than right-associative application,
and partly because I'm hedging my bets for Haskell 2 just in case the
standards committee wakes up and notices that the associativity of $ is
just plain wrong and decides to fix it. :-)

In fact, I'll go out on a limb and claim that ALL such uses of $ are
better expressed with composition.  Anyone care to come up with a
counter-example?

> But of course, left associative version can also be useful. Some
> time ago I used a left associative version of the strict application
> operator, which I named (!$).

In fact, I think it's much MORE useful, and for precisely the reason
that you state: it makes strict application much more natural.

Strict application also has the wrong associativity.  As it is, $! is
only useful if the _last_ argument of a function needs to be strict.  I
find that ordering my arguments in a de Bruijn-like order (which many
experienced functional programmers do unconsciously) results in this
being the least common case.

The last argument of a function is usually the induction argument: it's
almost invariably the subject of a top-level test.  The strictness
analyser invariably picks up that the argument is strict.  It's the OTHER
arguments you may need to evaluate early.

Suppose you have a function with three arguments, the second of which
needs to be strict.  I want to write something like this:

    f (g x) $! (h y) $ (j z)

What I have to write is this:

    (f (g x) $! (h y)) (j z)

or this:

    let y' = h y in y' `seq` f (g x) y' (j z)

> Anyway, you can't always remove all parentheses. And why would you want
> to? Everybody is used to them.

I agree.  However, sometimes parentheses make things more confusing.
Almost always the best solution is to give the offending subexpression
a name, using "let" or "where".  However, the specific case above is the
only one that I've found where this, too, makes things worse.

In summary: There is no good reason to make $ right-associative and at
least one good reason to make it left-associative.

Cheers,
Andrew Bromage
Tomasz Zielonka | 5 Feb 13:49
Picon

Re: Why is $ right associative instead of left associative?

On Sat, Feb 04, 2006 at 07:02:52PM -0500, ajb <at> spamcop.net wrote:
> G'day all.

Hello!

> Quoting Tomasz Zielonka <tomasz.zielonka <at> gmail.com>:
> 
> > Probably it was anticipated that right associative version will
> > be more useful. You can use it to create a chain of transformations,
> > similar to a chain of composed functions:
> >
> >     (f . g . h) x   =   f $ g $ h $ x
> 
> Of course, if $ were left-associative, it would be no less useful here,
> because you could express this chain thusly:
> 
>     f . g . h $ x

OK, I can be persuaded to use this style. I like function composition
much more than $ :-)

> This is the way that I normally express it.  Partly because I find
> function application FAR more natural than right-associative application,
> and partly because I'm hedging my bets for Haskell 2 just in case the
> standards committee wakes up and notices that the associativity of $ is
> just plain wrong and decides to fix it. :-)

Is there any chance that Haskell' will change the definition of $ ?

Well, if there is any moment where we can afford introducing backward
incompatible changes to Haskell', I think it's now or never!

> In fact, I'll go out on a limb and claim that ALL such uses of $ are
> better expressed with composition.  Anyone care to come up with a
> counter-example?

The only problem I see right now is related to change locality. If I
have a chain like this:

    f x y .
    g x $
    z

and I want to add some transformation between g and z I have to
change one line and insert another

    f x y .
    g x .
    h x y $
    z

With right-associative $ it would be only one line-add. Probably not a
very strong argument.

> > But of course, left associative version can also be useful. Some
> > time ago I used a left associative version of the strict application
> > operator, which I named (!$).
> 
> In fact, I think it's much MORE useful, and for precisely the reason
> that you state: it makes strict application much more natural.

Agreed.

Best regards
Tomasz

--

-- 
I am searching for programmers who are good at least in
(Haskell || ML) && (Linux || FreeBSD || math)
for work in Warsaw, Poland
ajb | 7 Feb 00:22
Favicon
Gravatar

Re: Why is $ right associative instead of left associative?

G'day all.

Quoting Tomasz Zielonka <tomasz.zielonka <at> gmail.com>:


> Is there any chance that Haskell' will change the definition of $ ? > > Well, if there is any moment where we can afford introducing backward > incompatible changes to Haskell', I think it's now or never!
I'm not convinced about this. The purpose of Haskell', as I understand it, is to fix the problem that no large Haskell programs (to a first approximation) are valid H98 because they require some quite reasonable language extensions. Partly this is because research is an ongoing area. Partly this is because the purpose of H98 was to make a simple language suitable for teaching. There _is_ a time coming when H98's true successor will need to be made. I'm not convinced that that time is now or never. Cheers, Andrew Bromage
Bill Wood | 5 Feb 22:12
Picon
Favicon

Re: Why is $ right associative instead of left associative?

On Sun, 2006-02-05 at 13:49 +0100, Tomasz Zielonka wrote:
   . . .
> and I want to add some transformation between g and z I have to
> change one line and insert another
> 
>     f x y .
>     g x .
>     h x y $
>     z

> With right-associative $ it would be only one line-add. Probably not a
> very strong argument.

Maybe stronger than you think.  I know that one of the arguments for
making ";" a C-style delimiter rather than a Pascal-style separator is
that adding a new statement at the end of a series is error-prone -- one
tends to forget to add the ";" in front of the new statement (and one
reason Pascal syntax included the "null" statement was so that "s1;"
would parse as "s1; null", making ";" a de facto delimiter).

Editing ease matters more than a little.

 -- Bill Wood
Brian Hulley | 5 Feb 14:14

Re: Why is $ right associative instead of leftassociative?


Tomasz Zielonka wrote: > The only problem I see right now is related to change locality. If I > have a chain like this: > > f x y . > g x $ > z > > and I want to add some transformation between g and z I have to > change one line and insert another > > f x y . > g x . > h x y $ > z > > With right-associative $ it would be only one line-add. Probably not a > very strong argument.
How about: f x y . g x $ z then you only need to add the line . h x y This is similar to how people often format lists: a = [ first , second , third ] Regards, Brian.
Tomasz Zielonka | 5 Feb 15:32
Picon

Re: Why is $ right associative instead of leftassociative?

On Sun, Feb 05, 2006 at 01:14:42PM -0000, Brian Hulley wrote:
> How about:
> 
>      f x y
>      . g x
>      $ z
> 
> then you only need to add the line
> 
>      . h x y

But then you have a problem when you when you want to add something
at the beginning ;-) With right-assoc $ adding at both ends is OK.

> This is similar to how people often format lists:
> 
>     a =
>          [ first
>          , second
>          , third
>          ]

I am one of those people, and I am slightly annoyed with I have to
add something at the beginning of the list. I even went so far that
when I had a list of lists, which were concatenated, I've put an
empty list at front:

    concat $
        [ []
        , [...]
        , [...]
        .
        .
        .
        ]

Best regards
Tomasz

--

-- 
I am searching for programmers who are good at least in
(Haskell || ML) && (Linux || FreeBSD || math)
for work in Warsaw, Poland
Henning Thielemann | 6 Feb 14:12
Picon

Re: Why is $ right associative instead of leftassociative?


On Sun, 5 Feb 2006, Tomasz Zielonka wrote:


> On Sun, Feb 05, 2006 at 01:14:42PM -0000, Brian Hulley wrote: > > > This is similar to how people often format lists: > > > > a = > > [ first > > , second > > , third > > ] > > I am one of those people, and I am slightly annoyed with I have to > add something at the beginning of the list.
In this case I prefer the non-sugar variant: a = first : second : third : []
Ben Rudiak-Gould | 5 Feb 19:58
Picon
Picon
Favicon

Re: Why is $ right associative instead of leftassociative?


Tomasz Zielonka wrote: > On Sun, Feb 05, 2006 at 01:14:42PM -0000, Brian Hulley wrote: >> How about: >> >> f x y >> . g x >> $ z > > But then you have a problem when you when you want to add something > at the beginning ;-)
How about: id . f x y . g x $ z -- Ben
Tomasz Zielonka | 5 Feb 20:34
Picon

Re: Re: Why is $ right associative instead of leftassociative?


On Sun, Feb 05, 2006 at 06:58:15PM +0000, Ben Rudiak-Gould wrote: > Tomasz Zielonka wrote: > >But then you have a problem when you when you want to add something > >at the beginning ;-) > > How about: > > id > . f x y > . g x > $ z
Yes, I've thought about it. You are using a neutral element of ., just like I used [] as a neutral element of ++ (or concat). Best regards Tomasz -- -- I am searching for programmers who are good at least in (Haskell || ML) && (Linux || FreeBSD || math) for work in Warsaw, Poland
Brian Hulley | 5 Feb 17:36

Re: Why is $ right associative instead of leftassociative?


Tomasz Zielonka wrote: > On Sun, Feb 05, 2006 at 01:14:42PM -0000, Brian Hulley wrote: >> How about: >> >> f x y >> . g x >> $ z >> >> then you only need to add the line >> >> . h x y > > But then you have a problem when you when you want to add something > at the beginning ;-) With right-assoc $ adding at both ends is OK. > >> This is similar to how people often format lists: >> >> a = >> [ first >> , second >> , third >> ] > > I am one of those people, and I am slightly annoyed with I have to > add something at the beginning of the list. I even went so far that > when I had a list of lists, which were concatenated, I've put an > empty list at front: > > concat $ > [ [] > , [...] > , [...] > . > . > . > ]
Just in case you are interested, in the "preprocessor" I'm writing, I would write these examples as: (.) #> f x y g x h x y $ z and a = #[ first second third where exp #> {e0,e1,...} is sugar for let a = exp in a e0 (a e1 (a ... ) ...)) and #[ {e0, e1, ... } is sugar for [e0, e1, ...] (exp #> block and exp #< block are the right and left associative versions respectively and the special # sugar allows a layout block to be started if it occurs at the end of a line) This allows me to avoid having to type lots of syntax eg repeating the "." all the time and focus on the semantics... Regards, Brian.
Tomasz Zielonka | 5 Feb 17:42
Picon

Re: Why is $ right associative instead of leftassociative?

On Sun, Feb 05, 2006 at 04:36:44PM -0000, Brian Hulley wrote:
> Just in case you are interested, in the "preprocessor" I'm writing, I would 
> write these examples as:
> 
>        (.) #>
>                   f x y
>                   g x
>                   h x y
>        $ z
> 
> and
>         a = #[
>                    first
>                    second
>                    third
> 
> where exp #> {e0,e1,...} is sugar for let a = exp in a e0 (a e1 (a ... ) 
> ...)) and #[ {e0, e1, ... } is sugar for [e0, e1, ...]            (exp #> 
> block and exp #< block are the right and left associative versions 
> respectively and the special # sugar allows a layout block to be started if 
> it occurs at the end of a line)

Well... I care about change locality and the like, but I'm not sure
I would use such syntax (as a means of communication between
programmers). Perhaps that's because I am not used to it and it looks
alien. But it's rather because I still put readability first.

> This allows me to avoid having to type lots of syntax eg repeating the "." 
> all the time and focus on the semantics...

At some point you (the programmer) are going to do the work of a
compression program ;-)

There is some limit to terseness. Haskell's syntax is quite concise, but
it could be even more. Why it isn't? Because it would cease to resemble
the mathematical notation, it would cease to be readable. Well, even
Haskell could be more readable, but there's also some point where
further investment in concise lexical syntax doesn't pay off. I am not
sure that's the situation here, but... think about it.

PS. One wonders why you don't take the lisp way with a good lisp editor?
    Aren't you designing lisp without parentheses? ;-)

Best regards
Tomasz

--

-- 
I am searching for programmers who are good at least in
(Haskell || ML) && (Linux || FreeBSD || math)
for work in Warsaw, Poland
Brian Hulley | 6 Feb 00:07

Re: Why is $ right associative instead of leftassociative?


Tomasz Zielonka wrote: > On Sun, Feb 05, 2006 at 04:36:44PM -0000, Brian Hulley wrote: >> Just in case you are interested, in the "preprocessor" I'm writing, >> I would write these examples as: >> >> (.) #> >> f x y >> g x >> h x y >> $ z >> >> and >> a = #[ >> first >> second >> third >> >> where exp #> {e0,e1,...} is sugar for let a = exp in a e0 (a e1 (a >> ... ) ...)) and #[ {e0, e1, ... } is sugar for [e0, e1, ...] >> (exp #> block and exp #< block are the right and left associative >> versions respectively and the special # sugar allows a layout block >> to be started if it occurs at the end of a line) > > Well... I care about change locality and the like, but I'm not sure > I would use such syntax (as a means of communication between > programmers). Perhaps that's because I am not used to it and it looks > alien. But it's rather because I still put readability first.
It is true that it looks quite alien at first, but consider that it allows you to use longer identifiers for function names (because they now only need to be written once) which could actually enhance readability eg Prelude.compose #> f x y g x h x y $ z so perhaps people would start using more real words instead of obscure symbols like >=+=< etc. Also, the less use of infix notation the better, because every infix symbol requires the reader to search for the fixity declaration then try to simulate a precedence parser at the same time as grappling with the semantics of the code itself. The #>, #< notation solves this problem by making the sugared associativity immediately visible, and the use of layout further enhances the direct visual picture of what's happening. Anyway it's just an idea I thought I'd share- I'm sure there's no danger of it ever ending up in a future Haskell... ;-) Regards, Brian.
ajb | 5 Feb 01:28
Favicon
Gravatar

Re: Why is $ right associative instead of left associative?

G'day all.

Quoting ajb <at> spamcop.net:


> This is the way that I normally express it. Partly because I find > function application FAR more natural than right-associative application,
I meant to say that I find function COMPOSITION more natural than right-associative application. It certainly fits better with my personal biases about good functional programming style. Cheers, Andrew Bromage
Brian Hulley | 5 Feb 02:47

Re: Why is $ right associative instead of leftassociative?


ajb <at> spamcop.net wrote: > G'day all. > > Quoting ajb <at> spamcop.net: > >> This is the way that I normally express it. Partly because I find >> function application FAR more natural than right-associative >> application, > > I meant to say that I find function COMPOSITION more natural than > right-associative application. It certainly fits better with my > personal biases about good functional programming style.
Yes the case you've made for $ being left associative is very compelling - namely that the existing associativity actively encourages a *bad* programming style in which the right associative $ hides the composition in a chain of function applications instead of allowing the composition to be explicit and neatly separate from its argument. Moreover, the existing associativity of $ implies that whoever thought it up was confusing two concepts: application and composition, instead of allowing "$" to take its proper place as an equal citizen to ".", with the associativity proper to its role as application alone. Thus if $ were made left associative in Haskell Prime, this would add clarity to the thought forms associated with the language, which would (presumably) in turn lead to better programs being written in it. Regards, Brian.
Brian Hulley | 4 Feb 19:02

Re: Why is $ right associative instead of left associative?

Tomasz Zielonka wrote:
> On Sat, Feb 04, 2006 at 02:52:20PM -0000, Brian Hulley wrote:
>> Hi -
>> In the Haskell98 report section 4.4.2 $ is specified as being right
>> associative. This means that f $ a0 a1 $ b0 b1 would parse as f (a0
>> a1 (b0 b1)) which seems rather strange to me. Surely it would be
>> much more useful if $ were defined as left associative so that it
>> could be used to separate the args to f?
>>
>> Does anyone know why this strange associativity was chosen?
>
> Probably it was anticipated that right associative version will
> be more useful. You can use it to create a chain of transformations,
> similar to a chain of composed functions:
>
>    (f . g . h) x   =   f $ g $ h $ x
>
> Example:
>
>    map f $ group $ sort $ filter g $ l
>
> But of course, left associative version can also be useful. Some
> time ago I used a left associative version of the strict application
> operator, which I named (!$).

I wonder if anyone has done empirical studies to determine scientifically 
which associativity would be more useful in practice eg by analysis of 
source code involving $ and comparing the number of parentheses that would 
be needed in each case, and perhaps also some studies involving the number 
of confused readers in each case...

Even though both versions are useful, it seems to me that faced with the 
choice of choosing an associativity for an operator that does function 
application, and given that prefix application is left associative, there is 
one clear winner, but unfortunately the Haskell committee didn't see it this 
way, and perhaps it is too late to ever change this (just like :: and : 
which were mixed up for reasons unknown). Especially since chains can 
already be composed using "." .

>
> Anyway, you can't always remove all parentheses. And why would you
> want to? Everybody is used to them.

$'s advertised purpose is to remove parentheses, but I agree that 
parenthesized code is often more readable (especially when operators have 
unexpected fixities... :-))

Regards, Brian. 
Brian Hulley | 4 Feb 20:15

Re: Why is $ right associative instead of leftassociative?

Brian Hulley wrote:
> Tomasz Zielonka wrote:
>> On Sat, Feb 04, 2006 at 02:52:20PM -0000, Brian Hulley wrote:
>>> Hi -
>>> In the Haskell98 report section 4.4.2 $ is specified as being right
>>> associative. This means that f $ a0 a1 $ b0 b1 would parse as f (a0
>>> a1 (b0 b1)) which seems rather strange to me. Surely it would be
>>> much more useful if $ were defined as left associative so that it
>>> could be used to separate the args to f?
>>>
>>> Does anyone know why this strange associativity was chosen?
>>
>> Probably it was anticipated that right associative version will
>> be more useful. You can use it to create a chain of transformations,
>> similar to a chain of composed functions:
>>
>>    (f . g . h) x   =   f $ g $ h $ x

Actually I'm beginning to think this might be more useful after all.

>>
>> Example:
>>
>>    map f $ group $ sort $ filter g $ l
>>
>> But of course, left associative version can also be useful. Some
>> time ago I used a left associative version of the strict application
>> operator, which I named (!$).

I suppose I could use $$ for left associative application, and #$$ for 
layout application.

>
> I wonder if anyone has done empirical studies to determine
> scientifically which associativity would be more useful in practice
> eg by analysis of source code involving $ and comparing the number of
> parentheses that would be needed in each case, and perhaps also some
> studies involving the number of confused readers in each case...
>
> Even though both versions are useful, it seems to me that faced with
> the choice of choosing an associativity for an operator that does
> function application, and given that prefix application is left
> associative, there is one clear winner, but unfortunately the Haskell
> committee didn't see it this way, and perhaps it is too late to ever
> change this (just like :: and : which were mixed up for reasons
> unknown). Especially since chains can already be composed using "." .

It would be very useful if the Haskell report explained *why* decisions were 
made, because there often seem to be good reasons that are not immediately 
obvious and sometimes counter intuitive. I think the mystery surrounding :: 
and : might have been that originally people thought type annotations would 
hardly ever be needed whereas list cons is often needed, but now that it is 
regarded as good practice to put a type annotation before every top level 
value binding, and as the type system becomes more and more complex (eg with 
GADTs etc), type annotations are now presumably far more common than list 
cons so it would be good if Haskell Prime would swap these operators back to 
their de facto universal inter-language standard of list cons and type 
annotation respectively.

Regards, Brian. 
Tomasz Zielonka | 4 Feb 20:42
Picon

Re: Why is $ right associative instead of leftassociative?


On Sat, Feb 04, 2006 at 07:15:47PM -0000, Brian Hulley wrote: > I think the mystery surrounding :: and : might have been that > originally people thought type annotations would hardly ever be needed > whereas list cons is often needed, but now that it is regarded as good > practice to put a type annotation before every top level value > binding, and as the type system becomes more and more complex (eg with > GADTs etc), type annotations are now presumably far more common than > list cons so it would be good if Haskell Prime would swap these > operators back to their de facto universal inter-language standard of > list cons and type annotation respectively.
I am not convinced. Even if you really want to write types for every top-level binding, it's only one :: per binding, which can have a definition spanning for many lines and as complicated type as you want. On the other hand, when you are doing complicated list processing, it is not uncommon to have four (or more) :'s per _line_. Personally, I started my FP adventure with OCaml (which has the thing the other way around), and I felt that the meanings of :: and : should be reversed - before I even knew Haskell! Best regards Tomasz -- -- I am searching for programmers who are good at least in (Haskell || ML) && (Linux || FreeBSD || math) for work in Warsaw, Poland
Brian Hulley | 4 Feb 21:59

Re: Why is $ right associative instead of leftassociative?

Tomasz Zielonka wrote:
> On Sat, Feb 04, 2006 at 07:15:47PM -0000, Brian Hulley wrote:
>> I think the mystery surrounding :: and : might have been that
>> originally people thought type annotations would hardly ever be
>> needed whereas list cons is often needed, but now that it is
>> regarded as good practice to put a type annotation before every top
>> level value binding, and as the type system becomes more and more
>> complex (eg with GADTs etc), type annotations are now presumably far
>> more common than list cons so it would be good if Haskell Prime
>> would swap these operators back to their de facto universal
>> inter-language standard of list cons and type annotation
>> respectively.
>
> I am not convinced. Even if you really want to write types for every
> top-level binding, it's only one :: per binding, which can have a
> definition spanning for many lines and as complicated type as you
> want. On the other hand, when you are doing complicated list
> processing, it is not uncommon to have four (or more) :'s per _line_.

I wonder if extending the sugared list syntax would help here. The | symbol 
is used for list comprehensions but something along the lines of:

        [a,b,c ; tail]      ===      a :: b :: c :: tail         -- where :: 
means list cons

then there would seldom be any need to use the list cons symbol anywhere 
except for sections. I would use "," instead of ";" in the block syntax so 
that ";" could be freed for the above use and so that there would be a 
generic block construct {,,,} that could be used for records also (and could 
always be replaced by layout) eg

        P {x=5, y=6}

could be written also as

        P #                        -- # allows a layout block to be started
              x = 5
              y = 6

>
> Personally, I started my FP adventure with OCaml (which has the thing
> the other way around), and I felt that the meanings of :: and : should
> be reversed - before I even knew Haskell!

I see what you mean ;-). However the swapping of :: and : really is very 
confusing when one is used to things being the other way round. Also in 
natural language, ":" seems to have a much closer resonance with the 
type/kind annotation meaning than with constructing a list. I also wonder if 
it is such a good idea to make lists so special? Does this influence our 
thinking subconciously to use list-based solutions when some other data 
structure may be better?

Regards, Brian. 
Jared Updike | 4 Feb 23:01
Picon
Gravatar

Re: Why is $ right associative instead of leftassociative?


> [a,b,c ; tail] === a :: b :: c :: tail -- where ::
How is [a,b,c ; tail] simpler, clearer or less typing than a:b:c:tail ? I think that the commas and semicolons are easy to confuse. While we're talking about the aesthetics of "::" and ":", I like how a line with a type annotation stands out strongly with "::", e.g. map :: (a -> b) -> [a] -> [b] Compare this to map : (a -> b) -> [a] -> [b] where the identifier looks more connected to the type. You will notice this is different than ML anyway because in Haskell you can separate the type annotation and the declaration. If you are designing your own langauge, you will of course have your own aesthetics and reasons for doing it your way. As for me, I started to design (in my head) the "perfect" language (for me), but the more I learned and used Haskell, the more I realized how carefully designed it was and how it was better for me to use my efforts to learn from Haskell (especially conceptually, since the syntax is so transparent and the ideas are so amazing) than to try to insert clever ideas to satisfy my own whims. Sure, there are always little things to nitpick, but on the whole, can you think of more succinct language with more power? (and less parentheses!) Plus, what other languages let you more easily add (infix) operators, etc. and change things to fit your whim, anyway (and still be strongly type!). Cheers, Jared. -- http://www.updike.org/~jared/ reverse ")-:"
Brian Hulley | 4 Feb 23:59

Re: Why is $ right associative instead of leftassociative?

Jared Updike wrote:
>>         [a,b,c ; tail]      ===      a :: b :: c :: tail         --
>> where ::
>
> How is [a,b,c ; tail]   simpler, clearer or less typing than
> a:b:c:tail  ? I think that the commas and semicolons are easy to
> confuse.

It seems strange that you can write [a,b,c] with a nice list sugar but if 
you want to include a tail you have to switch to the infix notation using 
list cons. Prolog for example allows you to write [a,b,c|Tail] but neither 
Haskell nor ML allows this. In Haskell, | is used to introduce a list 
comprehension so I was just trying to find a replacement symbol for when you 
want the equivalent of the Prolog list sugar so that you wouldn't be forced 
to use infix notation.

All this was not to replace a:b:c:tail but was to replace a::b::c::tail so 
that : could be used for type annotations instead.

>
> While we're talking about the aesthetics of "::" and ":", I like how a
> line with a type annotation stands out strongly with "::", e.g.
> map :: (a -> b) -> [a] -> [b]
> Compare this to
> map : (a -> b) -> [a] -> [b]
> where the identifier looks more connected to the type.

This is no doubt because you are used to thinking of : as meaning list cons 
whereas I find the :: notation confusing for precisely the same reason.

>
> If you are designing your own langauge, you will of course have your
> own aesthetics and reasons for doing it your way. As for me, I started
> to design (in my head) the "perfect" language (for me), but the more I
> learned and used Haskell, the more I realized how carefully designed
> it was and how it was better for me to use my efforts to learn from
> Haskell (especially conceptually, since the syntax is so transparent
> and the ideas are so amazing) than to try to insert clever ideas to
> satisfy my own whims. Sure, there are always little things to nitpick,
> but on the whole, can you think of more succinct language with more
> power? (and less parentheses!) Plus, what other languages let you more
> easily add (infix) operators, etc. and change things to fit your whim,
> anyway (and still be strongly type!).

I've spent at least 3 years looking into various languages (Prolog, ML, 
Scheme, Lisp, Logo, Smalltalk, Mozart) before finally arriving at the 
pleasant shores of Haskell which has an incredibly well thought out and neat 
syntax not to mention a powerful type system. However there are some things 
that are just plain crazy, such as the existing layout rule which forces you 
to use a monospaced font when it would have been so simple to make a simpler 
layout rule using tabs that would result in grammatically robust code in the 
face of identifier renamings and editor font choices (as I've indicated on 
other threads), and the way constructors and field labels for different 
types are allowed to collide with each other in a module's namespace.

Feedback from this forum has been invaluable in helping me find a solution 
to this second problem and arrive at a good field selection syntax with 
semantics based on a compiler-defined global typeclass for each field label, 
although it has taken at least 3 months to discover this...

There are some funny things with the semantics I'm puzzled about - such as 
why Haskell is still based on Hindley Milner type inference with its 
troublesome monomorphism restrictions instead of intersection types which 
would allow everything to be mutually recursive with separate compilation of 
modules etc, but AFAIK no other language uses intersection types yet either, 
and Haskell is at least heading in the right direction with arbitrary rank 
forall polymorphism.

So I agree that Haskell is one of the best languages in existence at the 
moment all things considered, especially because it is a very good place to 
start when trying to develop the "perfect" language.

Regards, Brian. 
Chris Kuklewicz | 5 Feb 00:34

Re: Why is $ right associative instead of leftassociative?


Brian Hulley wrote: > Jared Updike wrote: >>> [a,b,c ; tail] === a :: b :: c :: tail -- >>> where :: >> >> How is [a,b,c ; tail] simpler, clearer or less typing than >> a:b:c:tail ? I think that the commas and semicolons are easy to >> confuse. > > It seems strange that you can write [a,b,c] with a nice list sugar but > if you want to include a tail you have to switch to the infix notation > using list cons. Prolog for example allows you to write [a,b,c|Tail] but > neither Haskell nor ML allows this. In Haskell, | is used to introduce a > list comprehension so I was just trying to find a replacement symbol for > when you want the equivalent of the Prolog list sugar so that you > wouldn't be forced to use infix notation. > > All this was not to replace a:b:c:tail but was to replace a::b::c::tail > so that : could be used for type annotations instead. >
There is the .. operator which is unused in pattern matching contexts. So maybe case [1,3..] of [a,b,c,tail..] -> tail -- I like this one, the ..] catches the eye better [a,b,c,..tail] -> tail -- I think this is less clear at a glance [a,b,c,..tail..] -> tail -- I expect no one to like this [a,b,c,_..] -> [a,b,c] -- Not the best looking thing I've ever seen [a,b,c,.._] -> [a,b,c] -- ditto [a,b,c,.._..] -> [a,b,c] -- ick But this implies [a,b,c,[]..] is the same as [a,b,c] and [a,b,c,[d,e,f]..] is the same as [a,b,c,d,e,f] and [a,b,c,[d,e,f..]..] is [a,b,c,d,e,f..] Wacky.
Bill Wood | 5 Feb 01:00
Picon
Favicon

Re: Why is $ right associative instead of leftassociative?

On Sat, 2006-02-04 at 23:34 +0000, Chris Kuklewicz wrote:
   . . .
> But this implies [a,b,c,[]..] is the same as [a,b,c] and [a,b,c,[d,e,f]..] is
> the same as [a,b,c,d,e,f] and [a,b,c,[d,e,f..]..] is [a,b,c,d,e,f..]

Hmmm, does this get us to difference lists ala Prolog?

 -- Bill Wood
Stefan Holdermans | 4 Feb 21:55
Picon

Re: Why is $ right associative instead of leftassociative?


Brian wrote:


> I think the mystery surrounding :: and : might have been that > originally people thought type annotations would hardly ever be needed > whereas list cons is often needed, but now that it is regarded as good > practice to put a type annotation before every top level value > binding, and as the type system becomes more and more complex (eg with > GADTs etc), type annotations are now presumably far more common than > list cons so it would be good if Haskell Prime would swap these > operators back to their de facto universal inter-language standard of > list cons and type annotation respectively.
I don't think Haskell Prime should be about changing the look and feel of the language. Regards, Stefan
Paul Hudak | 4 Feb 22:21
Picon
Favicon

Re: Why is $ right associative instead of leftassociative?

Actually, one of the main reasons that we chose (:) is that that's what 
Miranda used.  So, at the time at least, it was not entirely clear what 
the "de facto universal inter-language standard" was.

In any case, I agree with Stefan regarding Haskell Prime!

   -Paul

Stefan Holdermans wrote:

> Brian wrote: > >> I think the mystery surrounding :: and : might have been that >> originally people thought type annotations would hardly ever be needed >> whereas list cons is often needed, but now that it is regarded as good >> practice to put a type annotation before every top level value >> binding, and as the type system becomes more and more complex (eg with >> GADTs etc), type annotations are now presumably far more common than >> list cons so it would be good if Haskell Prime would swap these >> operators back to their de facto universal inter-language standard of >> list cons and type annotation respectively. > > I don't think Haskell Prime should be about changing the look and feel > of the language. > > Regards, > > Stefan
ajb | 5 Feb 01:23
Favicon
Gravatar

Re: Why is $ right associative instead of leftassociative?

G'day all.

Quoting Paul Hudak <paul.hudak <at> yale.edu>:


> Actually, one of the main reasons that we chose (:) is that that's what > Miranda used. So, at the time at least, it was not entirely clear what > the "de facto universal inter-language standard" was.
Exactly. One point that's often not appreciated is that Haskell is not a descendent of ML. The ML lineage is, roughly: Lisp -> ISWIM -> ML -> SML, LML, O'Caml etc And the Haskell lineage is: Lisp -> ISWIM -> SASL -> KRC -> Miranda -> Haskell ML is much more like an older cousin than an ancestor. This point is important because Turner languages already had a list syntax at the time that they adopted an ML-like type system. Cheers, Andrew Bromage

Re: Why is $ right associative instead of leftassociative?

These lineages are more or less right, except that there is a bit of
incest: LML is certainly one of the progenitors of Haskell.  (more
semantically than syntactically, though)

Cheers,
--Joe

ajb <at> spamcop.net said:

> G'day all. > > Quoting Paul Hudak <paul.hudak <at> yale.edu>: > >> Actually, one of the main reasons that we chose (:) is that that's what >> Miranda used. So, at the time at least, it was not entirely clear what >> the "de facto universal inter-language standard" was. > > Exactly. One point that's often not appreciated is that Haskell is not > a descendent of ML. The ML lineage is, roughly: > > Lisp -> ISWIM -> ML -> SML, LML, O'Caml etc > > And the Haskell lineage is: > > Lisp -> ISWIM -> SASL -> KRC -> Miranda -> Haskell > > ML is much more like an older cousin than an ancestor. > > This point is important because Turner languages already had a list > syntax at the time that they adopted an ML-like type system. > > Cheers, > Andrew Bromage > _______________________________________________ > Haskell-Cafe mailing list > Haskell-Cafe <at> haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe >
Joseph H. Fasel, Ph.D. email: jhf <at> lanl.gov Stockpile-Complex Modeling and Analysis phone: +1 505 667 7158 University of California fax: +1 505 667 2960 Los Alamos National Laboratory post: D-2 MS F609; Los Alamos, NM 87545
Brian Hulley | 4 Feb 22:15

Re: Why is $ right associative instead of leftassociative?


Stefan Holdermans wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Brian wrote: > >> I think the mystery surrounding :: and : might have been that >> originally people thought type annotations would hardly ever be >> needed whereas list cons is often needed, but now that it is >> regarded as good practice to put a type annotation before every top >> level value binding, and as the type system becomes more and more >> complex (eg with GADTs etc), type annotations are now presumably far >> more common than list cons so it would be good if Haskell Prime >> would swap these operators back to their de facto universal >> inter-language standard of list cons and type annotation >> respectively. > > I don't think Haskell Prime should be about changing the look and > feel of the language.
Perhaps it is just a matter of aesthetics about :: and :, but I really feel these symbols have a de-facto meaning that should have been respected and that Haskell Prime would be a chance to correct this error. However no doubt I'm alone in this view so fair enough - it's just syntax after all and I can run my own programs through a pre-processor if I want them the other way round... :-) Regards, Brian.
Jon Fairbairn | 5 Feb 12:42
X-Face
Picon
Picon
Favicon

Re: Why is $ right associative instead of leftassociative?

On 2006-02-04 at 21:15GMT "Brian Hulley" wrote:
> Stefan Holdermans wrote:
> > -----BEGIN PGP SIGNED MESSAGE-----
> > Hash: SHA1
> >
> > Brian wrote:
> >
> >> I think the mystery surrounding :: and : might have been that
> >> originally people thought type annotations would hardly ever be
> >> needed whereas list cons is often needed, but now that it is
> >> regarded as good practice to put a type annotation before every top
> >> level value binding, and as the type system becomes more and more
> >> complex (eg with GADTs etc), type annotations are now presumably far
> >> more common than list cons so it would be good if Haskell Prime
> >> would swap these operators back to their de facto universal
> >> inter-language standard of list cons and type annotation
> >> respectively.
> >
> > I don't think Haskell Prime should be about changing the look and
> > feel of the language.
> 
> Perhaps it is just a matter of aesthetics about :: and :, but I really feel 
> these symbols have a de-facto meaning that should have been respected and 
> that Haskell Prime would be a chance to correct this error. However no doubt 
> I'm alone in this view so fair enough

Not exactly alone; I've felt it was wrong ever since we
argued about it for the first version of Haskell. ":" for
typing is closer to common mathematical notation.

But it's far too late to change it now.

> - it's just syntax after all

It is indeed.

  Jón

--

-- 
Jón Fairbairn                              Jon.Fairbairn at cl.cam.ac.uk
Brian Hulley | 5 Feb 14:10

Re: Why is $ right associative instead of leftassociative?


Jon Fairbairn wrote: > Brian Hulley wrote: >> <snip> > > Not exactly alone; I've felt it was wrong ever since we > argued about it for the first version of Haskell. ":" for > typing is closer to common mathematical notation. > > But it's far too late to change it now. > >> - it's just syntax after all
Well I'm reconsidering my position that it's "just" syntax. Syntax does after all carry a lot of semiotics for us humans, and if there are centuries of use of ":" in mathematics that are just to be discarded because someone in some other language decided to use it for list cons then I think it makes sense to correct this. It would be impossible to get everything right first time, and I think the Haskell committee did a very good job with Haskell, but just as there can be bugs in a program, so there can also be bugs in a language design, and an interesting question is how these can be addressed. For example, in the Prolog news group several years ago, there was also a discussion about changing the list cons operator, because Prolog currently uses "." which is much more useful for forming composite names - something which I also think has become a de-facto inter-language standard. Although there was much resistance from certain quarters, several implementations of Prolog had in fact changed their list cons operator (list cons is hardly ever needed in Prolog due to the [Head|Tail] sugar) to reclaim the dot for its "proper" use. My final suggestion if anyone is interested is as follows: 1) Use ":" for types 2) Use "," instead of ";" in the block syntax so that all brace blocks can be replaced by layout if desired (including record blocks) 3) Use ";" for list cons. ";" is already used for forming lists in natural language, and has the added advantage that (on my keyboard at least) you don't even need to press the shift key! ;-) Regards, Brian.
X-Face
Picon

Re: Why is $ right associative instead of leftassociative?


"Brian Hulley" <brianh <at> metamilk.com> writes: > My final suggestion if anyone is interested is as follows: > > 1) Use ":" for types > 2) Use "," instead of ";" in the block syntax so that all brace blocks > can be replaced by layout if desired (including record blocks) > 3) Use ";" for list cons. ";" is already used for forming lists in > natural language, and has the added advantage that (on my keyboard at > least) you don't even need to press the shift key! ;-)
My language uses \ for cons, and ? for lambda. -- -- __("< Marcin Kowalczyk \__/ qrczak <at> knm.org.pl ^^ http://qrnik.knm.org.pl/~qrczak/
John Hughes | 5 Feb 16:13
Picon
Picon

Re: Why is $ right associative instead ofleftassociative?

Lennart Augustsson wrote:

 > I now think :: for type signatures was a bad mistake.
 > I don't use lists very much.  They are not the right data structure
 > for many things.  So : is not as common as :: in my code.
 > I checked a small sample of code, about 20000 lines of Haskell.
 > It has about 1000 uses of ':' and 2000 of '::'.

Just for interest, I analysed some of my code. Obviously my style is
quite different to yours--my type specialiser of 3,500 lines has 240
conses, and only 22 occurrences of '::'. I seem to be using '::'  a bit more
lately, though, which I suspect is due to using classes much more.
I also checked the Agda source code, about 14,000 lines, with
about 500 occurrences of cons and 640 of '::'. I think the only conclusion
one can draw is that style varies.

 > In my opinion all the special syntactic sugar for lists should go
 > away.  I don't think lists are special enough to motivate it.

What, no list comprehensions??

I'd disagree--sequencing is special, and lists represent it directly.
Don't forget, also, that lists are also much more prevalent in beginners'
code--and nice notation for beginners helps get people started on
Haskell.

 > But this is not what Haskell' is about.  It's supposed to be some
 > modest extensions to Haskell.  Not designing a new perfect language.

Right!

John
Lennart Augustsson | 5 Feb 16:45
Favicon

Re: Why is $ right associative instead ofleftassociative?

John Hughes wrote:
> What, no list comprehensions??

No.  I think the do notation is good enough.

> 
> I'd disagree--sequencing is special, and lists represent it directly.
> Don't forget, also, that lists are also much more prevalent in beginners'
> code--and nice notation for beginners helps get people started on
> Haskell.

I don't really see what's so much better about writing
[x1,x2,x3,x4,x5] than x1:x2:x3:x4:x5:[].
When I've explained lists to beginners I've just found it
annoying and hard to explain why there are two ways of
writing lists.  And why only lists have this special syntax.

	-- Lennart
Cale Gibbard | 6 Feb 07:18
Picon

Re: Why is $ right associative instead ofleftassociative?


On 05/02/06, Lennart Augustsson <lennart <at> augustsson.net> wrote: > John Hughes wrote: > > What, no list comprehensions?? > > No. I think the do notation is good enough. > > > > > > I'd disagree--sequencing is special, and lists represent it directly. > > Don't forget, also, that lists are also much more prevalent in beginners' > > code--and nice notation for beginners helps get people started on > > Haskell. > > I don't really see what's so much better about writing > [x1,x2,x3,x4,x5] than x1:x2:x3:x4:x5:[]. > When I've explained lists to beginners I've just found it > annoying and hard to explain why there are two ways of > writing lists. And why only lists have this special syntax. > > -- Lennart
Lists have special syntax because they're the lazy-functional counterpart to loops. They're quite a fundamental structure, regardless of what other data types we may have at our disposal, and I think that lots of special support is reasonable. Loops in imperative languages often get all kinds of special syntax support, and I don't think it's too far off-base to give lists special syntax accordingly. That said, I'd *really* like to see monad comprehensions come back, since they align better with the view that monads are container types, dual to the view that monads are computations, which is supported by the do-syntax. This view is actually much easier to teach (in my experience). Giving lists a little extra syntax is nice, but giving things unnecessarily restrictive types seems to be the point at which I'd consider it going too far. I haven't thought this out too carefully, but perhaps in order to give the brackets and commas syntax some more weight, the syntax x1:x2:x3:[] (or x1:x2:x3:Nil ?) could be used solely as a list, but [x1,x2,x3] would be the corresponding element in any MonadPlus -- this would be quite handy in a lot of the cases which I care about (nondeterministic computation). It would also mesh perfectly with monad comprehensions. I'd also like to mention that although my background is in pure mathematics, I had no trouble whatsoever adjusting to :: meaning "has type". A colon is commonly inserted in mathematics between the name of a function and a depiction of the domain and codomain with an arrow between them, but I wouldn't think of that as formal syntax per-se. Also, it's not centuries-old as mentioned, but only about 50 years old -- I believe it started with the use of arrows in category theory. Before then, people mostly stated the types of functions in words, or it was left completely implicit, and they still often do both of those. Also, it is only used for functions and doesn't apply to values in any set or concrete categorical object. The notation x : S to mean x is an element of S is not in widespread common use. The use and context in mathematics is sufficiently different that I don't see it as a concern that Haskell be the same in this regard. The aesthetic reason that I like :: for "has type" and : for cons is that it's far more common that type signatures occur on a line by themselves, whereas conses when needed are often needed in bunches on the same line. Not that I'm suggesting that we change things, but as an example, I actually wouldn't mind typing out "has type" for type declarations (though the symbolic form is awfully nice when things must be annotated in-line, because it looks more like a separator rather than some random words -- syntax colouring could make up for that though), whereas I would likely mind a larger symbol for list cons. The amount of typing isn't the concern, it's how it actually looks on the page, and where it occurs in use. The wishy-washy informal reasoning is that cons is like a small bit of punctuation between the elements of a list -- semantically a comma, whereas a type annotation is actually saying something. When reading code aloud, you might not even say 'cons', and if you do say something, it'll probably be something fairly short and punctuation-like whereas for a type annotation, you're almost certainly going to say 'has type' or 'is of type', which seems structurally 'larger' to me, and perhaps deserves a bigger, more noticeable representation on the page. - Cale
John Hughes | 6 Feb 08:39
Picon
Picon

Re: Why is $ right associative instead ofleftassociative?


Cale Gibbard wrote: >That said, I'd *really* like to see monad comprehensions come back, >since they align better with the view that monads are container types, >dual to the view that monads are computations, which is supported by >the do-syntax. This view is actually much easier to teach (in my >experience). Giving lists a little extra syntax is nice, but giving >things unnecessarily restrictive types seems to be the point at which >I'd consider it going too far. > > >
The trouble with monad comprehensions was that it became far too easy to write ambiguous programs, even when you thought you were just working with lists. Haskell overloading works really nicely *as long as there's a judicious mixture of overloaded and non-overloaded functions*, so that the overloading actually gets resolved somewhere. Overload too many things, and you end up having to insert type annotations in the middle of expressions instead, which really isn't nice. Lists are special, not least because they come very early in a Haskell course--or, in my case, in the first ever programming course my students have ever taken. Getting error messages about ambiguous overloading when they are still trying to understand what comprehension notation means (without even the concept of a for-loop to relate it to) is very destructive. And this is in the case where the code is otherwise type-correct--the kind of error message you would get by trying to append a number to a monad comprehension doesn't bear thinking about! The class system is already something of an obstacle in teaching, because you have to mention it in the context of arithmetic (even if you tell students always to write monomorphic type signatures, they still see classes mentioned in error messages). After all, that is surely why Helium doesn't have it. I find classes manageable for arithmetic, even if students do take some time to learn to distinguish between a class and a type (or a type and a value, for that matter!). But it's a relief that list programs, at least, have simple non-overloaded types. List functions provide an opportunity to introduce polymorphism in a simple context--it's much easier to understand why (++) should have the type [a] -> [a] -> [a], than to start talking about MonadPlus m => m a -> m a -> m a. There is a lot to learn in Haskell, especially in the type and class system. It's an advantage if you don't have to learn it all at once--if you can master lists and list comprehensions without exposure to monads (which are a much harder concept). We should never forget that beginners have somewhat different needs from expert programmers--and those needs are also important. If we want Haskell to be used for first programming courses (and it's a big advantage to catch 'em early), then there needs to be a learning path into the language that goes quite gently. Monomorphic lists help with that. We did consider more aggressive defaulting to address the ambiguity problems with monad comprehensions--defaulting Monad to lists, for example, or user-declared defaulting rules--but this introduces yet more complexity without really addressing the problem of keeping types simple for beginners, so the idea was abandoned. John
Stefan Monnier | 8 Feb 07:34
Picon

Re: Why is $ right associative instead ofleftassociative?


> The trouble with monad comprehensions was that it became far too easy to > write ambiguous programs, even when you thought you were just working with > lists.
One solution was already suggested: to make the comprehension syntax be pure syntactic sugar whose semantics depends on the semantics of the identifiers the syntactic sugar expands into. So you could keep the current list-only comprehension as default, and allow monad comprehension by providing a library (which the users need to import so as to hide the Prelude's definition). Stefan
Jan-Willem Maessen | 8 Feb 14:15
Picon
Favicon

Re: Re: Why is $ right associative instead ofleftassociative?


On Feb 8, 2006, at 1:34 AM, Stefan Monnier wrote:

>> The trouble with monad comprehensions was that it became far too  
>> easy to
>> write ambiguous programs, even when you thought you were just  
>> working with
>> lists.
>
> One solution was already suggested: to make the comprehension  
> syntax be pure
> syntactic sugar whose semantics depends on the semantics of the  
> identifiers
> the syntactic sugar expands into.

OK.  Which identifiers?  I happen to want a version which always uses  
"concatMap" (or, equivalently, monadic bind), and never, ever the  
direct "efficient" translation.  To get the efficient translation for  
lists a la Wadler, though, this requires either a wrapper, so that  
the comprehension runs at the type ([a] -> [a]) and gets applied to  
[] at the very end, or it requires heavy lifting from the compiler  
(foldr/build and its kin as seen in GHC, phc, etc.).

When it was all tied to lists, it was easy to gloss over the details  
of the machinery.

-Jan-Willem Maessen

> So you could keep the current list-only comprehension as default,  
> and allow
> monad comprehension by providing a library (which the users need to  
> import
> so as to hide the Prelude's definition).
>
>
>         Stefan
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe <at> haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
Taral | 6 Feb 22:31
Picon

Re: Why is $ right associative instead ofleftassociative?


On 2/6/06, John Hughes <rjmh <at> cs.chalmers.se> wrote: > The trouble with monad comprehensions was that it became far too easy to > write ambiguous programs, even when you thought you were just working > with lists.
Would the Haskell98-style solution be to add defaulting for Monads? -- Taral <taralx <at> gmail.com> "Computer science is no more about computers than astronomy is about telescopes." -- Edsger Dijkstra
Bulat Ziganshin | 6 Feb 10:35
Favicon

Re[2]: Why is $ right associative instead ofleftassociative?

Hello John,

Monday, February 06, 2006, 10:39:59 AM, you wrote:


>>That said, I'd *really* like to see monad comprehensions come back,
JH> We did consider more aggressive defaulting to address the ambiguity JH> problems with monad comprehensions--defaulting Monad to lists, for JH> example, or user-declared defaulting rules--but this introduces yet more JH> complexity without really addressing the problem of keeping types simple JH> for beginners, so the idea was abandoned. why not allow some sort of module-wide pragma to "enable" use of this and any other features for expert programmers? just recalling last "import extension" proposal, we can add: import extension i-am-expert-programmer-enable-monad-comprehension-pleeeeease! :) -- -- Best regards, Bulat mailto:bulatz <at> HotPOP.com
Cale Gibbard | 6 Feb 10:23
Picon

Re: Why is $ right associative instead ofleftassociative?


On 06/02/06, John Hughes <rjmh <at> cs.chalmers.se> wrote: > Cale Gibbard wrote: > > >That said, I'd *really* like to see monad comprehensions come back, > >since they align better with the view that monads are container types, > >dual to the view that monads are computations, which is supported by > >the do-syntax. This view is actually much easier to teach (in my > >experience). Giving lists a little extra syntax is nice, but giving > >things unnecessarily restrictive types seems to be the point at which > >I'd consider it going too far. > > > The trouble with monad comprehensions was that it became far too easy to > write ambiguous programs, even when you thought you were just working > with lists. Haskell overloading works really nicely *as long as there's > a judicious mixture of overloaded and non-overloaded functions*, so that > the overloading actually gets resolved somewhere. Overload too many > things, and you end up having to insert type annotations in the middle > of expressions instead, which really isn't nice. > > Lists are special, not least because they come very early in a Haskell > course--or, in my case, in the first ever programming course my students > have ever taken. Getting error messages about ambiguous overloading when > they are still trying to understand what comprehension notation means > (without even the concept of a for-loop to relate it to) is very > destructive. And this is in the case where the code is otherwise > type-correct--the kind of error message you would get by trying to > append a number to a monad comprehension doesn't bear thinking about! > > The class system is already something of an obstacle in teaching, > because you have to mention it in the context of arithmetic (even if you > tell students always to write monomorphic type signatures, they still > see classes mentioned in error messages). After all, that is surely why > Helium doesn't have it. I find classes manageable for arithmetic, even > if students do take some time to learn to distinguish between a class > and a type (or a type and a value, for that matter!). But it's a relief > that list programs, at least, have simple non-overloaded types. List > functions provide an opportunity to introduce polymorphism in a simple > context--it's much easier to understand why (++) should have the type > [a] -> [a] -> [a], than to start talking about MonadPlus m => m a -> m a > -> m a. > > There is a lot to learn in Haskell, especially in the type and class > system. It's an advantage if you don't have to learn it all at once--if > you can master lists and list comprehensions without exposure to monads > (which are a much harder concept). We should never forget that beginners > have somewhat different needs from expert programmers--and those needs > are also important. If we want Haskell to be used for first programming > courses (and it's a big advantage to catch 'em early), then there needs > to be a learning path into the language that goes quite gently. > Monomorphic lists help with that. > > We did consider more aggressive defaulting to address the ambiguity > problems with monad comprehensions--defaulting Monad to lists, for > example, or user-declared defaulting rules--but this introduces yet more > complexity without really addressing the problem of keeping types simple > for beginners, so the idea was abandoned. > > John > >
How about a compiler switch for beginners (maybe with an included script that adds it to the command line) that turns off a bunch of the more complex issues involved, and uses a beginner's version of the Prelude? Helium exists as well, which is a simplified version of Haskell for beginners, without even typeclasses. It has very careful and detailed error messages. Having monad comprehensions actually helps with another newbie problem, albeit one which is a little farther along the garden path -- learning about monads. Defaulting monad comprehensions is probably a good idea. List comprehensions are probably the most common case anyway, just because lists are the most common container type. :) This also further helps in introducing monads as generalisations of lists. If extensions to the language get standardised, I'd be fine with having monad comprehensions among them. Adding an extension declaration or compiler switch to any module using them wouldn't be so bad either, though I'd really like them in the actual language. I'd also want to include the usual changes to the prelude. The situation with map I find especially grating. Having two versions of common functions is one thing, but 3 is getting out there! :) Is explaining Functor really that hard? It's just container types with a way to apply a function to all of their elements. :) I don't think it should be necessary to completely rule out useful features because they might be difficult to newcomers. There should always be ways to turn things off, and construct a simpler language for new users. Dr. Scheme seems to take this approach, and has a pretty fine gradation of languages for leading users from their first steps into the finer points of Scheme. (I'm not completely sure how well Dr. Scheme works in practice as I haven't used it a whole lot myself, but the idea is great, and it certainly looks quite nice.) Also, it seems that classes are one of the first things one has to teach now anyway, as they're bound to come up in error messages in any actual programs you try to write. When teaching my friend, I taught the basics of classes along with types in the first and second lesson (including how to define them) and presented various values and functions as examples. Perhaps certain error messages would still be confusing after a basic intro to classes, but I think that improving error messages would help quite a lot here. :) GHC's ability to suggest common fixes is fairly useful (though occasionally misleading). An automatic (interactive?) glossary for terms like 'unresolved overloading' would be quite good. It would also be nice to offer links in error messages to the Haskell wiki, where users could discuss common reasons and fixes for a given error. - Cale
John Hughes | 6 Feb 11:14
Picon
Picon

Re: Why is $ right associative instead ofleftassociative?

Cale Gibbard wrote:

>How about a compiler switch for beginners (maybe with an included
>script that adds it to the command line) that turns off a bunch of the
>more complex issues involved, and uses a beginner's version of the
>Prelude? 
>
Well, right now, the complex issues are turned off by having separate types
and separate functions, which works pretty well. Would such a switch
resolve overloading silently to "beginners' types"? If so, some code would
compile with the switch, but not without it--which is pretty scary. You'd
need to check when compiling each module whether it was "beginners"
or not.

>Is explaining
>Functor really that hard? It's just container types with a way to
>apply a function to all of their elements. :)
>
>Also, it seems that classes are one of the first things one has to
>teach now anyway, as they're bound to come up in error messages in any
>actual programs you try to write. When teaching my friend, I taught
>the basics of classes along with types in the first and second lesson
>(including how to define them) and presented various values and
>functions as examples.
>  
>
Something tells me your friend wasn't an undergraduate of only moderate
ability, with no programming experience of any kind. Honestly, the 
difference
between a singleton list and its element is a big deal at this 
stage--words like
"container types" would go right over almost all students' heads. You're 
right
that classes must be mentioned early, but there's no need for more than 
a very
basic understanding. I tell my students always to write type signatures 
at the
start, so the error messages they see say things like "No instance Num 
Bool".
I just tell them that means booleans aren't numbers--they don't need to even
see a class or instance definition to understand that.

    I don't think it should be necessary to completely rule out useful
    features because they might be difficult to newcomers. There should
    always be ways to turn things off, and construct a simpler language
    for new users. Dr. Scheme seems to take this approach, and has a
    pretty fine gradation of languages for leading users from their first
    steps into the finer points of Scheme.

It would be interesting to see a "Dr. Scheme" like approach to Haskell.
But there is a risk with that approach--namely, that students get the
impression (correctly) that they are learning a toy language which isn't
usable for real applications. That is a big-time motivation killer.
(I'm not criticizing Dr Scheme here, but rather how I imagine a flag
of the sort we're discussing might work with Haskell). It's important
that there is a smooth route to infinity and beyond, so one can show
students cool stuff like wxHaskell without discontinuities along the way.
Otherwise they're just glad to finish their Haskell course, and move
on to a real programming language like Java.

Separate syntax for easy and more difficult concepts--separating
comprehensions from do--does provide a very smooth progression for
beginners.

John
Tomasz Zielonka | 5 Feb 16:46
Picon

Re: Why is $ right associative instead ofleftassociative?


On Sun, Feb 05, 2006 at 10:45:50AM -0500, Lennart Augustsson wrote: > I don't really see what's so much better about writing > [x1,x2,x3,x4,x5] than x1:x2:x3:x4:x5:[]. > When I've explained lists to beginners I've just found it > annoying and hard to explain why there are two ways of > writing lists. And why only lists have this special syntax. > > -- Lennart
But if you remove the [...] syntax, there will be more :'s in people's code. You are working against yourself here ;-) Best regards Tomasz -- -- I am searching for programmers who are good at least in (Haskell || ML) && (Linux || FreeBSD || math) for work in Warsaw, Poland
Tomasz Zielonka | 5 Feb 18:56
Picon

Re: Why is $ right associative instead of leftassociative?


On Sun, Feb 05, 2006 at 01:10:24PM -0000, Brian Hulley wrote: > 2) Use "," instead of ";" in the block syntax so that all brace blocks can > be replaced by layout if desired (including record blocks)
Wouldn't it be better to use ; instead of , also for record syntax? Best regards Tomasz -- -- I am searching for programmers who are good at least in (Haskell || ML) && (Linux || FreeBSD || math) for work in Warsaw, Poland
Brian Hulley | 5 Feb 19:19

Re: Why is $ right associative instead of leftassociative?


Tomasz Zielonka wrote: > On Sun, Feb 05, 2006 at 01:10:24PM -0000, Brian Hulley wrote: >> 2) Use "," instead of ";" in the block syntax so that all brace >> blocks can be replaced by layout if desired (including record blocks) > > Wouldn't it be better to use ; instead of , also for record syntax?
I thought of this also, but the nice thing about using commas everywhere is that it is consistent with tuples and lists: [a,b,c] (a,b,c) {a,b,c} I admit it takes some getting used to to write: map f (h;t) = f h;map f t but you couldn't use commas in tuple syntax if they were also used as list cons. Also, I'm using test :{Eq a, Show a} a -> () instead of test :: (Eq a, Show a) => a->() and the comma here is particularly nice because it suggests a set, which is exactly what the context is. Regards, Brian.
Aaron Denney | 5 Feb 18:30
X-Face

Re: Why is $ right associative instead of leftassociative?


On 2006-02-05, Brian Hulley <brianh <at> metamilk.com> wrote: > Jon Fairbairn wrote: >> Brian Hulley wrote: >>> <snip> >> >> Not exactly alone; I've felt it was wrong ever since we >> argued about it for the first version of Haskell. ":" for >> typing is closer to common mathematical notation. >> >> But it's far too late to change it now. >> >>> - it's just syntax after all > > Well I'm reconsidering my position that it's "just" syntax. Syntax does > after all carry a lot of semiotics for us humans, and if there are centuries > of use of ":" in mathematics that are just to be discarded because someone > in some other language decided to use it for list cons then I think it makes > sense to correct this. > > It would be impossible to get everything right first time, and I think the > Haskell committee did a very good job with Haskell, but just as there can be > bugs in a program, so there can also be bugs in a language design, and an > interesting question is how these can be addressed. > > For example, in the Prolog news group several years ago, there was also a > discussion about changing the list cons operator, because Prolog currently > uses "." which is much more useful for forming composite names - something > which I also think has become a de-facto inter-language standard. Although > there was much resistance from certain quarters, several implementations of > Prolog had in fact changed their list cons operator (list cons is hardly > ever needed in Prolog due to the [Head|Tail] sugar) to reclaim the dot for > its "proper" use. > > My final suggestion if anyone is interested is as follows: > > 1) Use ":" for types > 2) Use "," instead of ";" in the block syntax so that all brace blocks can > be replaced by layout if desired (including record blocks) > 3) Use ";" for list cons. ";" is already used for forming lists in natural > language, and has the added advantage that (on my keyboard at least) you > don't even need to press the shift key! ;-) > > Regards, Brian.
If anything, using ',' for block syntax and ';' for lists is backwards. ',' is used for generic lists in English, whereas ';' is used for seperating statements or lists. But I like the current syntax just fine. -- -- Aaron Denney -><-
Cale Gibbard | 4 Feb 22:50
Picon

Re: Why is $ right associative instead of leftassociative?


On 04/02/06, Brian Hulley <brianh <at> metamilk.com> wrote: > Stefan Holdermans wrote: > > -----BEGIN PGP SIGNED MESSAGE----- > > Hash: SHA1 > > > > Brian wrote: > > > >> I think the mystery surrounding :: and : might have been that > >> originally people thought type annotations would hardly ever be > >> needed whereas list cons is often needed, but now that it is > >> regarded as good practice to put a type annotation before every top > >> level value binding, and as the type system becomes more and more > >> complex (eg with GADTs etc), type annotations are now presumably far > >> more common than list cons so it would be good if Haskell Prime > >> would swap these operators back to their de facto universal > >> inter-language standard of list cons and type annotation > >> respectively. > > > > I don't think Haskell Prime should be about changing the look and > > feel of the language. > > Perhaps it is just a matter of aesthetics about :: and :, but I really feel > these symbols have a de-facto meaning that should have been respected and > that Haskell Prime would be a chance to correct this error. However no doubt > I'm alone in this view so fair enough - it's just syntax after all and I can > run my own programs through a pre-processor if I want them the other way > round... :-) > > Regards, Brian. >
In Haskell, they have a de-facto meaning which is opposite to the one you're talking about :) Besides, lots of papers and various other programming languages use Haskell's convention (which was taken from Miranda). - Cale

Gmane