[GHC] #10047: inconsistency in name binding between splice and quasiquotation
GHC
ghc-devs at haskell.org
Thu Jun 4 19:39:09 UTC 2015
#10047: inconsistency in name binding between splice and quasiquotation
-------------------------------------+-------------------------------------
Reporter: rwbarton | Owner:
Type: bug | Status: new
Priority: normal | Milestone: 7.12.1
Component: Template Haskell | Version: 7.8.4
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: None/Unknown | Unknown/Multiple
Blocked By: | Test Case: th/T10047
Related Tickets: | Blocking:
| Differential Revisions:
-------------------------------------+-------------------------------------
Comment (by spinda):
Firstly, at least as far as I've seen, the scoping restriction is one of
the most common complaints about Template Haskell splices, as using them
at all suddenly causes order of declaration to matter where it didn't
before. This contributes to the stigma and avoidance of Template Haskell
usage. It would be a shame to see quasiquoters get shackled with this
issue as well.
Then, I think it's important to consider the role of quasiquoters as
enabling extensions to the language without requiring compiler plugins,
external preprocessors, or what have you, while keeping them contained
from the rest of the Haskell source around them. As a specific example,
I'll pull from my current GSoC project, which is impacted by this change
(and, to be honest, is the reason I ran into this).
I have an {{{lq}}} quasiquoter which allows for LiquidHaskell type
signatures and specifications to be attached to variables and types. In
the declaration context, it parses a subset of Haskell with LiquidHaskell
extensions and emits declarations and annotations. Take some vanilla
Haskell code:
{{{
module Test () where
type Nat = Int
add :: Nat -> Nat -> Nat
add x y = id' $ x + y
id' :: a -> a
id' x = x
}}}
A little contrived, but not too far from what you'd run into in
sufficiently complex real-world projects. Under the current (or, previous)
quasiquoter implementation, extending this existing code with custom
annotations is a fairly straightforward translation:
{{{
{-# LANGUAGE QuasiQuotes #-}
module Test () where
import LiquidHaskell
[lq| type Nat = { v:Int | 0 <= v } |]
[lq| add :: Nat -> Nat -> Nat |]
add x y = id' $ x + y
[lq| id' :: x:a -> { v:a | v == a } |]
id' x = x
}}}
But after this change, introducing these annotations suddenly makes order
of declaration matter. What were lightweight inline extensions to the
language now require restructuring of code, either reordering the
functions themselves or moving all signatures and specifications to the
top of every file. Needless to say, this makes the whole thing much less
attractive.
And, frankly, this is what quasiquoters are all about: lightweight, inline
language extensions that don't interfere with the rest of the code. This
intent is reflected in the original paper. With this restriction imposed,
anything using quasiquoters suddenly brings in a lot more baggage than it
used to, discouraging use. It's not just a matter of modifying some
existing code to fit, it's that this hampers a whole set of use-cases for
which quasiquoters (a) used to fit quite nicely and (b) are the only real
solution at present.
Quietly breaking this behavior of 12 years now in a tangentially related
bugfix strikes me as, well, wrong, especially when there isn't an
alternative available. Excuse me if I seem rather passionate about this
issue.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10047#comment:9>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list