After the first report, I’ve done various tasks, so let’s go over them one by one:
The first task was to implement the part of GHC proposal #448 Modern Scoped Type Variables about extension shuffling.
Short description: ScopedTypeVariables
extension does three different things. Firstly, it enables pattern signatures:
not (a :: Bool) = Prelude.not a
-- ↑ disallowed without ScopedTypeVariables
The second thing the extension does is add type variables from a type class and an instance head into the scope of its methods:
class C a where
f :: a -> a
f x = (x :: a) -- `a` scoped from the class head
-- and
instance C a => C (Identity a) where
f = coerce @(a -> a) f
-- ↑ `a` scoped from the instance head
And the third one is about scoping type variables from forall
everywhere:
id :: forall a . a -> a
id x = (x :: a)
f = Left @a :: forall a . a -> Either a ()
-- and so on
With proposal #448 these would be three different extensions: PatternSignatures
, MethodTypeVariables
, and ExtendedForAllScope
. ScopedTypeVariables
will simply enable them all. I did this split up in !10385.
The proposal in the section I am describing also declares a new extension ImplicitForAll
that allows you to control if you want to have implicit forall’s and a new warning - -Wpattern-signature-binds
that warns about type variable binding in pattern signature, but currently, they are under discussion. I have a merge request with -Wpattern-signature-binds
implemented, but I’m not sure that it will be merged into master: !10585.
Next, I did a couple of small documentation improvements: !10327 and !10366.
The first of them just describe ImplicitParams
extension behavior more precisely. GHC must always use the most nested binding of the implicit variable:
f = let ?foo = 5 in let ?foo = 6 in ?foo -- `f` must be 6. If it isn't, then GHC has a bug
data D where
MkD :: (?foo :: Int) -> D
g MkD MkD = ?foo -- here ?foo must come from the second matching
If GHC violates this behavior (I hope it will not anyway), you can point to the new section of the GHC User’s Guide in an issue description.
The second documentation improvement mentions nubOrd
from the containers
package as a better alternative to the nub
function from the base
in nub
's haddock.
After that, I addressed issue #22558. Here GHC allows haddock comments, that should be rejected:
module
-- | Bad comment for the module
T17544_kw where
data Foo -- | Bad comment for MkFoo
where MkFoo :: Foo
newtype Bar -- | Bad comment for MkBar
where MkBar :: () -> Bar
class Cls a
-- | Bad comment for clsmethod
where
clsmethod :: a
I reanimated two merge requests that in conjunction solve this issue: !9476 and !9477. The first of them adds tokens module
, signature
, data
, newtype
, class
, where
into Haskell AST and updates all the places that use updated constructors. The second one applies these tokens in GHC.Parser.PostProcess.Haddock
to reject malformed comments. These merge requests a ready, but no one wants to review them (x1).
Then in discussion under my merge requests with extension shuffling was found an issue with -Wterm-variable-capture
: #23434. This warning notifies you if you have an implicitly bound type variable that has the same name as a term-level variable, but it ignores the fact that the type variable may be bound in the type class head
k = 12
class C k a where
type AT a :: k -> Type
-- ↑ `k` bound in the class head, but
-- `-Wterm-variable-capture` produces
-- warning
I fixed this issue in the merge request !10548, but no one wants to review it (x2).
And at the end, I solved an old issue !16635. Here the problem is in a scoping distinction between term level and type level:
{-# LANGUAGE ScopedTypeVariables #-}
-- f :: [forall b . Either b ()]
f = [Right @a @() () :: forall a. Either a ()] -- works
type F = '[Right @a @() () :: forall a. Either a ()] -- doesn't work
-- ↑ not in scope
The complication is that we can’t elaborate this type into Core. In term level GHC at desugaring phase inserts lambda with a type variable, so introduces binder for a
f = [(\@a -> Right @a @() ()) :: forall a . Either a ()]
But in types we can’t do the same, because we have no lambda in types
type F = '[(/\ a . Right @a @() ()) :: forall a. Either a ()]
-- ↑ not in haskell :(
We want to unify term level and type level, but we can’t elaborate this type with the current GHC. The partial solution is to move the error from the renaming phase to the elaboration phase, and that is what I did in the merge request !10560. It is also ready for review, but no one wants to do that (x3).
And that’s all for this week! GHC team, please, review my patches.