Packages icon indicating copy to clipboard operation
Packages copied to clipboard

[Haskell] constructors(or constants) are highlighted as types(storage.type)

Open absop opened this issue 3 years ago • 8 comments

What happened?

As the following image shows, for codes of Haskell, constructors(or constants) are highlighted as storage.type.

image

absop avatar Apr 10 '22 09:04 absop

That's a known limitation as it is not yet very clear how to reliably distinguish constants and types in normal expressions.

deathaxe avatar Apr 10 '22 12:04 deathaxe

That's a known limitation as it is not yet very clear how to reliably distinguish constants and types in normal expressions.

I think in normal expressions, there are no types, types are only occurs in type declarations. Maybe I am wrong, but for most case, that's it.

The punctuations :: and = can be used to identify and distinguish between type expressions and normal expressions.

absop avatar Apr 10 '22 13:04 absop

The type and value should be evaluated separately, that is, a normal expression should not have a type as an argument, except as an annotation that indicates the type of the argument's value.

absop avatar Apr 10 '22 13:04 absop

And there some other problem, see the following comparison.

GitHub

data Node = Node Int Node Node | Leaf

isLeaf, isNode :: Node -> Bool
isNode (Node value left right) = True
isNode _ = False
isLeaf node = not (isNode (node :: Node))

SublimeText

image

I believe GitHub also uses push-down automata for syntactic highlighting, not semantic highlighting.

This code can be compiled by GHC. I don't know why the comma is marked red and the token Leaf is marked as storage.type in the image above, but normal in the image below image

absop avatar Apr 10 '22 13:04 absop

There are several situations Github's and all those other TextMate syntaxes' highlighting fails, too, especially if expressions like types use several lines.

Haskell just doesn't provide enough boundaries to pop a context off stack reliably. It mainly works based on indentation level, which ST's engine can't make use of. Most syntaxes use a couple of heuristics to pop off those contexts, which often heavily depend on coding style. Or they just use naive patterns, which fail as soon as an expression requires 2 or more lines.

It's even not reliably possible to find the end of type expressions, without introducing a bunch of edge cases. The illegal comma you complain about is only one of them. In order to highlight constructor definitions a dedicated context needs to pushed on stack, but how to know isLeaf not being a type variable with more type expression terms following? The pattern, which looks for the end of this context, just assumes a simple assignment (ident = ) or function definition (ident ::).

Trying to distinguish more stuff, will likely just introduce more highlighting issues.

deathaxe avatar Apr 10 '22 14:04 deathaxe

In order to highlight constructor definitions a dedicated context needs to pushed on stack, but how to know isLeaf not being a type variable with more type expression terms following?

isLeaf is at the begin of one line, so it can't be a type variable.

In addition, Leaf is marked as storage.type, which is also a problem.

absop avatar Apr 10 '22 14:04 absop

There are several situations Github's and all those other TextMate syntaxes' highlighting fails, too, especially if expressions like types use several lines.

It's actually not that easy to fail.

data Node = Node 
  Int Node Node | Leaf

isLeaf, isNode :: Node -> Bool
isNode (Node value left right) = True
isNode _ = False
isLeaf node = not (isNode (node :: Node))

f :: Node ->
     Node ->
     Node -> Bool
f n1 n2 n3 = False

g :: Node ->
     Node -> Node ->
     Node -> Bool
g n1 n2 n3 n4 = False

h :: Node ->
     Node -> Node 
     -> Node -> Bool
h n1 n2 n3 n4 = False

absop avatar Apr 10 '22 14:04 absop

If it is so easy - hey - it's an open source project. Everyone can contribute valuable improvements.

deathaxe avatar Apr 10 '22 14:04 deathaxe