Open freeman42x opened 4 years ago
There is a language extension default enabled that is affecting parsing. The question is which one.
So, HLint default enables TemplateHaskell
and I believe that affects the parse so that $(
is considered a template Haskell token. I believe there are two solutions (1) write {-# LANGUAGE NoTemplateHaskell #-}
or (2) add whitespace between the $
and the (
.
Passing -XNoTemplateHaskell
on the command line or in the .hlint.yaml
file (see the README) works too to disable parsing. I guess this is obfuscated competition in some way?
@ndmitchell This is from Codingame Clash of Code in the shortest mode. The goal is not obfuscation but getting the code that gives correct results with as few characters as possible.
Thanks for the context @razvan-flavius-panda. So adding -XNoTemplateHaskell
should be enough.
But I wonder if disabling TemplateHaskell
by default might be reasonable? When we were on HSE, we often had to disable/enable lots of languages. Since moving to GHC, TemplateHaskell
has come up, but everything else has been things where the author definitely should fix the code.
Maybe. It does seem to be coming up somewhat often recently.
On the other hand, there is no escaping the fact that whitespace sensitive operator lexing is becoming more prevalent in modern Haskell (think !
, @
etc.). With this in mind and in this particular instance, despite the desire to minimize chars one might make a fair argument for requiring disambiguation of the token $(
from the sequence $
, (
.
I guess that argument would be, "stable in the presence of language extensions".
For this case, -XNoTemplateHaskell
is the right choice. However, a character-constrained program is a very rare special case, so I think you're right the general advice is probably to add enough spaces to not clash.
For this case,
-XNoTemplateHaskell
is the right choice. However, a character-constrained program is a very rare special case, so I think you're right the general advice is probably to add enough spaces to not clash.
I do agree -XNoTemplateHaskell
here is the way to go.
A suggestion: Would it perhaps be a possible to add a way to enable/disable specific extensions hlint
loads inside .hlint.yaml
on a per-module basis? Something like
- use-extensions:
- name: NoPatternSynonyms
within: My.Module.That.Got.A.Syntax.Error
- name: NoTemplateHaskell
within: Some.Other.Module
I ran into a similar issue with PattternSynonyms
in code that uses pattern
as a variable name, and adding a language pragma to explicitly disable it inside of the module seems like I'm doing it at the wrong level of concern. Since it's just for the sake of placating the linter, it should go in the linter configuration, in my opinion. We do use pattern synonyms elsewhere in the project, so I can't pass -XNoPatternSynonyms
to hlint
as a global option.
Given that you don't have a problem in this module, I imagine the modules you do use PatternSynonyms must have explicitly turned it on? If so, disable pattern synonyms globally in HLint, and then HLint will still honour the module-level pragmas overriding the global one. That should work universally in all cases, as all you are doing is reflecting the .cabal settings in the .hlint.yaml (albeit with different defaults for some extensions).
Personally though, you have a project where some modules use pattern as a variable and some use it as a keyword. I'd remove all uses of pattern as a variable for human comprehension, so its consistent.
Oh yes, you are right. Disabling them globally in HLint is what I ended up doing, and I think it makes sense in this instance.
One complicating factor that I forgot to mention is that we are using a multi-cabal setup with a cabal.project
file in a monorepo with many different packages, some of which with diverging sets of globally enabled extensions that have grown organically over time. We should probably enforce a repo-wide set of extensions using the global options available in the cabal.project
file, but we aren't quite there just yet.
Following code which compiles and runs:
throws the following parse error: