Re: [Haskell-cafe] Re: A better syntax for qualified operators?

2006-10-19 Thread Brian Smith
On Wed, Oct 18, 2006 at 04:42:00PM +0100, Simon Marlow wrote:> So you won't be able to colour patterns differently from expressions, that
> doesn't seem any worse than the context vs. type issue.  Indeed, I'm not> even sure you can colour types vs. values properly, look at this:>>   data T = C [Int]>> at this point, is C a constructor?  What if I continue the declaration like
> this:>>   data T = C [Int] `F`Haskell is easier than Java in this type of situation because Haskell's VARID and CONID are the same whereas Java's VARID and CONID are lexically equivalent. Modern Java IDE's color them correctly by doing (at least) two passes of highlighting: one during lexing and one after renaming/typechecking. As a result, they color identifiers based on lots of semantic information including their scope, visibility, and other factors. IntelliJ will even do data flow analsys to color an identifier differently within a single method depending on whether or not the variable can be null at each occurrence.
I think that an editor for Haskell would need to use a similar technique to be useful. For example, I want top-level values colored differently than local values, and I want exported, non-exported, imported, and unbound identifiers highlighted differently. And, I want parameters to be highlighted based on their strictness (determined automatically). This cannot generally be done until the entire module (as well as all of the modules it depends on) have been parsed.
In summary, I think that doing any syntax highlighting or other analysis of a Haskell module before it has gone through the renaming phase is a dead end.Regards,Brian
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: A better syntax for qualified operators?

2006-10-18 Thread John Meacham
On Wed, Oct 18, 2006 at 04:42:00PM +0100, Simon Marlow wrote:
> The other notorious part of the Haskell grammar that isn't LL/LR(1) is 
> expressions vs. patterns.  In a statement, if you see a variable, you don't 
> know whether it is a pattern variable (apat) or an expression variable 
> (aexpr).  This is why Haskell grammars generally parse expressions and 
> patterns using the same non-terminals.

it should be noted that all of haskell (including the maximal munching
rules and lexing (but not the layout without a little preprocessing
AFAIK)) can easily be parsed by a PEG. I am going to switch jhc to using
one eventually as the maintainability advantages of a peg grammar are
persuasive (and I pull my hair out every time I have to modify the
current happy LALR parser). 

If you are writing something like a syntax highlighter for an editor,
I'd strongly recommend checking them out as a basis. they are a
straightforward generalization of regular expressions and can be made to
deal gracefully with errors simply choosing the "most plausable" choice
from ambiguous or incomplete code, something that is extremely useful
for an editor.


> >By LL(1) I'm really meaning that the grammar for interactive editing 
> >needs to be adjusted so that it is possible to maintain the invariant 
> >that as code is entered from left to right constructs and identifiers 
> >can be highlighted according to their grammatical role and highlighting 
> >(modulo incompleteness) must remain unchanged regardless of whatever is 
> >typed afterwards to the right otherwise it can become more of a 
> >liability than a help, hence my hope that some future revision of 
> >Haskell grammar might consider taking the above points into account.
> 
> So you won't be able to colour patterns differently from expressions, that 
> doesn't seem any worse than the context vs. type issue.  Indeed, I'm not 
> even sure you can colour types vs. values properly, look at this:
> 
>   data T = C [Int]
> 
> at this point, is C a constructor?  What if I continue the declaration like 
> this:
> 
>   data T = C [Int] `F`

no problem for a PEG as the infinite lookahead allows it to see the `F`
no matter how far away it is.

jhc may give horrible type errors, but by golly it's gonna give some
good parse errors. :)

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: A better syntax for qualified operators?

2006-10-18 Thread Simon Marlow

Brian Hulley wrote:

When you try to write an editor for Haskell (or some subset of it), you 
quickly discover these areas of Haskell syntax like the above which need 
to be changed to get an optimum interactive editing experience. I think 
it *is* possible to adjust the Haskell grammar so that it is LL(1) and 
the only reason it is not already LL(1) seems to be that the grammar has 
been designed with compilers (which only need to deal with complete 
modules) in mind rather than programmers interactively editing in mind.


(The other change needed for LL(1) is to give contexts a marker before 
they appear eg:


   foo :: {MonadIO m} a -> m a
)


Just catching up on haskell-cafe...

The other notorious part of the Haskell grammar that isn't LL/LR(1) is 
expressions vs. patterns.  In a statement, if you see a variable, you don't know 
whether it is a pattern variable (apat) or an expression variable (aexpr).  This 
is why Haskell grammars generally parse expressions and patterns using the same 
non-terminals.


By LL(1) I'm really meaning that the grammar for interactive editing 
needs to be adjusted so that it is possible to maintain the invariant 
that as code is entered from left to right constructs and identifiers 
can be highlighted according to their grammatical role and highlighting 
(modulo incompleteness) must remain unchanged regardless of whatever is 
typed afterwards to the right otherwise it can become more of a 
liability than a help, hence my hope that some future revision of 
Haskell grammar might consider taking the above points into account.


So you won't be able to colour patterns differently from expressions, that 
doesn't seem any worse than the context vs. type issue.  Indeed, I'm not even 
sure you can colour types vs. values properly, look at this:


  data T = C [Int]

at this point, is C a constructor?  What if I continue the declaration like 
this:

  data T = C [Int] `F`

now it's a type!

Cheers,
Simon
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: A better syntax for qualified operators?

2006-09-29 Thread Brian Hulley

Benjamin Franksen wrote:

Brian Hulley wrote:

ith = Data.Array.IArray.(!)


Sorry, but I can't see the problem here. Why can't the editor offer
the operator as '!' in the list of options, and if the user selects
it insert both '(' and ')' at the right places (i.e. before the
module name and after the operator)? Is there some unwritten law that
forbids editors or IDEs to insert stuff at positions other than the
current cursor position?


I hadn't thought of that - I've now decided to just use the existing syntax 
here.




Generally speaking, I would always hesitate to change the language so
it better suits programming tools(*). It is the tools which should
adapt to the language, even if that means the programmer has to find
new ways of suporting the user (and the language). The most important
reason being that code is more often read than written.


My motivation for the change was that it would better suit the human user of 
the programming tool, though in this particular instance you and Henning 
have convinced me that the original syntax was better after all.




At the danger of becoming completely off-topic now (sorry!), I have
to say that I find /both/ versions ugly and unnecessarily hard to
read. My personal solution is to generally avoid qualified imports.


How does this solution scale? Surely it's only lucky if people happen to 
choose names that don't clash with those of other modules?



I use it only if absolutely necessary to disambiguate some symbol, and
then just for that symbol. I am aware that there is an opposing
faction here, who tries to convinve everyone that qualified import
should be the standard (and the actual exported symbols --at least
some of them-- meaningless, such as 'C' or 'T').


Although C and T are in themselves meaningless, the name of the module 
itself is not. As I understand it, this convention makes the module name 
carry the meaning so you use Set.T instead of Set.Set where the meaning is 
duplicated (a rather uneasy situation) in both the module name and type 
name.



I think such a
convention is inappropriate for a functional language (especially one
with user defined operators). There simply is no natural 1:1
correspondence between data type declaration and functions acting on
that data built into the language, as opposed to e.g. OO languages.
Extensibility in the functional dimension, i.e. the ability to
arbitrarily add functions that operate on some data without having to
change the code (module) that defines the data, is one of the
hallmarks of functional programming, as opposed to OO
programming.


If you have an abstract data type then it *is* like an object (though in a 
potentially more powerful way than in OOP) because there is no other way to 
manipulate values of that type.
If the type is not abstract, the advantage of calling it T is just that it 
avoids naming it twice (by type name and module name) in the situation where 
you want to not worry about name clashes with constructors of other types.



However, nothing prevents us from offering two
interfaces (visible modules), one where the data type is abstract ("client
interface") and a different one where it is concrete ("extension
interface")


You can still call both types T... :-)

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: A better syntax for qualified operators?

2006-09-28 Thread Benjamin Franksen
Brian Hulley wrote:
> Consider the scenario when you want to find a function that returns the
> i'th element of an array but all you know is that there is a module called
> Data.Array.IArray that will probably have such a function in it. So you
> start typing in your program:
> 
> let
> ith = Data.Array.IArray.
> 
> at this point, you'd hope the editor you're using would somehow display a
> list of avaliable values exported from Data.Array.IArray including the
> indexing function, so you could select it, thus I would *like* to be able
> to use the syntax:
> 
> let
> ith = Data.Array.IArray.(!)
> 
> because it's not the user's fault that the person who wrote
> Data.Array.IArray decided to use a symbol instead of an identifier for
> this function - the user of Data.Array.IArray in this case just wants to
> see normal identifiers to use with prefix application so the use of (!) at
> this point effectively gets rid of the unwanted operatorness associated
> with the function.
> 
> However the current syntax of Haskell would not allow this. Instead you
> have to write:
> 
> let
> ith = (Data.Array.IArray.!)
> 
> The problem is that the user of Data.Array.IArray has to know already in
> advance, before typing the 'D' of "Data", that the indexing function has
> been named with a symbol instead of an identifier, but this knowledge is
> only available later, when the user has typed the '.' after "IArray", so
> the current syntax would be frustrating for the user because the user then
> has to go all the way back and insert an opening paren before the 'D'.

Sorry, but I can't see the problem here. Why can't the editor offer the
operator as '!' in the list of options, and if the user selects it insert
both '(' and ')' at the right places (i.e. before the module name and after
the operator)? Is there some unwritten law that forbids editors or IDEs to
insert stuff at positions other than the current cursor position?

Isn't Haskell (assuming you are programming your editor in Haskell) not
supposed to make hard things easy(er)? Rather than complain about libraries
that offer operators (which i personally like very much, thank you) or
proposing to change the language, use your imagination and design a new
human interface that deals with the language in the most useful way. [BTW,
I recommend you take a look at what Conor BcBride did to support 'visual'
(dependently typed) programming in Epigram. There's many good ideas there
to steal from ;)]

Generally speaking, I would always hesitate to change the language so it
better suits programming tools(*). It is the tools which should adapt to
the language, even if that means the programmer has to find new ways of
suporting the user (and the language). The most important reason being that
code is more often read than written.

That said, there still might be good arguments to change the syntax in the
way you propose, just not the one you gave above. In fact, I am half of a
mind to say I like Data.Array.IArray.(!) better than (Data.Array.IArray.!).
My reason is that the former is more readable because it highlights the
operator symbol by surrounding it with parentheses, whereas the latter
obscures it.

At the danger of becoming completely off-topic now (sorry!), I have to say
that I find /both/ versions ugly and unnecessarily hard to read. My
personal solution is to generally avoid qualified imports. I use it only if
absolutely necessary to disambiguate some symbol, and then just for that
symbol. I am aware that there is an opposing faction here, who tries to
convinve everyone that qualified import should be the standard (and the
actual exported symbols --at least some of them-- meaningless, such as 'C'
or 'T'). I think such a convention is inappropriate for a functional
language (especially one with user defined operators). There simply is no
natural 1:1 correspondence between data type declaration and functions
acting on that data built into the language, as opposed to e.g. OO
languages. Extensibility in the functional dimension, i.e. the ability to
arbitrarily add functions that operate on some data without having to
change the code (module) that defines the data, is one of the hallmarks of
functional programming, as opposed to OO programming.(**)

Cheers
Ben
--
(*) Yes I know it has at least to be compilable, preferably in an efficient
way. However, that doesn't invalidate the argument. Indeed, it is bad
enough that we have to compromise in order to make our languages
implementable with current compiler technology. No need to compromise on
much less essential equipment, such as syntax aware editing tools.

(**) One could argue that this extensibility is lost anyway as soon
as /abstract/ data types come into play. However, [warning: it gets even
more off-topic from here on] nothing prevents us from offering /two/
interfaces (visible modules), one where the data type is abstract ("client
interface") and a different one where it is concrete ("ex