GHC: Ticket Query
http://ghc.haskell.org/trac/ghc/query?status=!closed&reporter=nfrisby&order=priority
The Glasgow Haskell Compileren-USGHChttp://ghc.haskell.org/trac/ghc/chrome/site/ghc_logo.png
http://ghc.haskell.org/trac/ghc/query?status=!closed&reporter=nfrisby&order=priority
Trac 1.0.1
http://ghc.haskell.org/trac/ghc/ticket/5542
http://ghc.haskell.org/trac/ghc/ticket/5542#5542: also parse class/instance declarations as "HEAD <= CONTEXT where"Sun, 09 Oct 2011 16:17:15 GMTnfrisby<p>
When looking at a list of instance declarations, it can be difficult to visually locate the instance heads. In particular, the varying size of the contexts means that it's difficult to align the instance heads without introducing extraneous white-space.
</p>
<p>
I suggest allowing the head to come first (like all other declarations), so that the varying context lengths no longer prevent easy identification of the class/instance heads.
</p>
<p>
For example, I think it's easier to see which instances are being declared in this following list of (,) instances
</p>
<pre class="wiki">instance Bounded (a, b) <= (Bounded a, Bounded b) where …
instance Eq (a, b) <= (Eq a, Eq b) where …
instance Functor ((,) a) where …
instance Ord (a, b) <= (Ord a, Ord b) where …
instance Read (a, b) <= (Read a, Read b) where …
instance Show (a, b) <= (Show a, Show b) where …
</pre><p>
than it is with the default syntax
</p>
<pre class="wiki">instance (Bounded a, Bounded b) => Bounded (a, b) where …
instance (Eq a, Eq b) => Eq (a, b) where …
instance Functor ((,) a) where …
instance (Ord a, Ord b) => Ord (a, b) where …
instance (Read a, Read b) => Read (a, b) where …
instance (Show a, Show b) => Show (a, b) where …
</pre><p>
A more compelling example would involve multiparameter type classes and juxtaposition of instances for different combinations of types.
</p>
<p>
(Bonus: the proposed ordering might even help beginner grasp that the instance context is not used for instance selection.)
</p>
Resultshttp://ghc.haskell.org/trac/ghc/ticket/5542#changelog
http://ghc.haskell.org/trac/ghc/ticket/5590
http://ghc.haskell.org/trac/ghc/ticket/5590#5590: "guarded instances": instance selection can add extra parameters to the classFri, 28 Oct 2011 05:19:55 GMTnfrisby<p>
Disclaimer: the same semantics can currently be achieved without this syntax. So this is mostly a Parser request, though I've made it a Type Checker request because some type errors would probably need to be aware of the language extension. More on this at the bottom.
</p>
<p>
We'll start with a demonstration. Just some ancillary declarations for now.
</p>
<pre class="wiki">class Sat t where dict :: t
data True; data False
type family Pred (p :: * -> *) a
type family Left a; type instance (Either l r) = l
type family Right a; type instance (Either l r) = r
data Path p a where
Here :: p a -> Path p a
L :: Path p l -> Path p (Either l r)
R :: Path p r -> Path p (Either l r)
</pre><p>
The objective of these declarations is to allow us to define some <tt>Pred</tt>icate <tt>p</tt> and use the <tt>Sat</tt> class to find a path leading through a tree of <tt>Either</tt>s to a type that satisfies that <tt>Pred</tt>icate.
</p>
<p>
These next three declarations use the new syntax, as I'm imagining it.
</p>
<pre class="wiki">-- NB new syntax: `guard' keyword, the pipe after the instance head,
-- and a comma-separated list of types after that
instance guard Sat (Path a)
| Pred p a, Pred (Path p) (Left a), Pred (Path p) (Right a)
-- now we match on the instance guards, using the same pipe syntax
instance Sat (p a) => Sat (Path p a) | True , satl , satr where
dict = Here dict
instance Sat (Path p l) => Sat (Path p (Either l r)) | False, True , satr where
dict = SL dict
instance Sat (Path p r) => Sat (Path p (Either l r)) | False, False, True where
dict = SR dict
</pre><p>
The <tt>guard</tt> declaration asserts that any instance of <tt>Sat</tt> with a head that <em>would</em> overlap a la <tt>OverlappingInstances</tt> with <tt>Path a</tt> shall be disambiguated via the comma-separated list of types following the pipe. In this example, the subsequent three instances, which would traditionally overlap, are indeed disambiguated by their additional "instance head guards" (cf. HList's type-level programming style: <a class="ext-link" href="http://www.haskell.org/haskellwiki/GHC/AdvancedOverlap"><span class="icon"></span>AdvancedOverlap</a>).
</p>
<p>
We can currently simulate this syntax by declaring a variant class of `Sat' which takes an extra parameter and thread the instance guards through that. Unfortunately, this workaround is repetitive, misses out on the better type error messages possible with specific Type Checker support, and it's just a bother.
</p>
<pre class="wiki">class Sat_ a anno where dict_ :: anno -> a
instance (anno ~ (Pred p a, Pred (Path p) (Left a), Pred (Path p) (Right a)),
Sat_ (Found a) anno) => Sat (Path p a) where
dict = dict_ (undefined :: anno)
instance Sat (p a) => Sat_ (Path p a) (True, satl, satr) where
dict_ _ = Here dict
…
</pre><p>
In the spirit of <a class="new ticket" href="http://ghc.haskell.org/trac/ghc/ticket/4259" title="feature request: Relax restrictions on type family instance overlap (new)">#4259</a>, <a class="wiki" href="http://ghc.haskell.org/trac/ghc/wiki/TypeFunctions/TotalFamilies">total type families</a>, and <a class="ext-link" href="http://www.haskell.org/haskellwiki/GHC/AdvancedOverlap"><span class="icon"></span>AdvancedOverlap</a>, this syntax could be enriched and thereby promoted to an actual Type Checker extension. Replacing the comma-separated list of types in the <tt>guard</tt> declaration with a sequence of contexts would be appropriate syntax for explicitly making instance selection sensitive to those contexts. The instance head guards could then just be a type boolean (wired-in to the compiler, now) indicating whether the context was satisfied. A <tt>True</tt> would bring that context's consequences to bear within both the instance's own context and its declarations. For example, we could do without the <tt>Left</tt> and <tt>Right</tt> type families.
</p>
<pre class="wiki">instance guard Sat (Path a)
| (Pred p a) (a ~ Either l r, Pred (Path p) l) (a ~ Either l r, Pred (Path p) r)
instance Sat (p a) => Sat (Path p a) | True satl satr where
dict = Here dict
…
</pre>Resultshttp://ghc.haskell.org/trac/ghc/ticket/5590#changelog
http://ghc.haskell.org/trac/ghc/ticket/7829
http://ghc.haskell.org/trac/ghc/ticket/7829#7829: make better/more robust loopbreaker choicesThu, 11 Apr 2013 18:41:00 GMTnfrisby<p>
The choice of loopbreaker can severely influence downstream compilation. This task ticket is about making the choice more robust/better/"smarter". This ticket is also empty of concrete suggestions how to do so... think of it like a community <span class="wikiextras phrase todo">TODO</span>.
</p>
<p>
One example feature of the current algorithm that seems a bit fragile is the use of two schemes for breaking ties depending on the max "depth" of 2. Peruse the code and its comments and Notes in OccAnal if you're interested.
</p>
<p>
This also ticket serves to document a small regression incurred by my commit <a class="changeset" href="http://ghc.haskell.org/trac/ghc/changeset/af12cf66d1a416a135cb98b86717aba2cd247e1a/ghc" title="ignore RealWorld in size_expr; flag to keep w/w from creating sharing
...">af12cf66d1a416a135cb98b86717aba2cd247e1a</a>. There's a 4% increase in allocation in nofib/rewrite as a result of my change altering the loopbreaker choice.
</p>
<p>
The actual details aren't relevant, but here's the basic story in order to convey the delicacy of loopbreaker choice. My commit slightly reduces the calculated size of a function in a mutually recursive group, so that it comes in under the "never unfold limit" instead of over. This ultimately causes the looperbreaker chooser to break a tie in a different way (there's two "Plans"). The previous choice was more fortuitous: it enabled a beneficial inlining that "misses its chance" with the new choice of loopbreaker.
</p>
<p>
I don't remember nor ever totally understood the details of this last part of the story. I don't have the cycles at the moment to wade into it -dverbose-core2core -ddump-inlings again. Apologies. If a brave soul is interested, you should be able to recover the more fortuitous loopbreaker choice by setting <tt>CoreUnfolding.sizeExpr.isRealWorldId</tt> to <tt>const False</tt>.
</p>
Resultshttp://ghc.haskell.org/trac/ghc/ticket/7829#changelog
http://ghc.haskell.org/trac/ghc/ticket/8050
http://ghc.haskell.org/trac/ghc/ticket/8050#8050: add a required wrapper around plugin installersWed, 10 Jul 2013 17:41:08 GMTnfrisby<p>
While trying to expand <a href="http://www.haskell.org/ghc/docs/7.6.1/html/users_guide/compiler-plugins.html#writing-compiler-plugins">the CoreMonad.reinitializeGlobals mechanism</a>, I proposed an alternative that SPJ noted could be more generally useful.
</p>
<p>
The nub of the idea is to require plugins to apply a distinguished function to their installation function. Instead of defining the plugin as
</p>
<pre class="wiki">module APlugin (plugin) where
import GhcPlugins
plugin :: Plugin
plugin = defaultPlugin {installCoreToDos = install}
install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]
install = …
</pre><p>
plugins would be defined as
</p>
<pre class="wiki">module APlugin (plugin) where
import GhcPlugins
plugin :: Plugin
plugin = defaultPlugin {installCoreToDos = mkPluginInstaller install}
install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]
install = install = …
</pre><p>
The new function <tt>mkPluginInstaller</tt> provides a hook for GHC developers to process the plugin, hidden from the plugin author. For example, it could encapsulate the current <tt>reinitializeGlobals</tt> mechanism.
</p>
<p>
I'm not sure if using an abstract type to enforce that this function is called is necessary, but it's an option.
</p>
Resultshttp://ghc.haskell.org/trac/ghc/ticket/8050#changelog
http://ghc.haskell.org/trac/ghc/ticket/8516
http://ghc.haskell.org/trac/ghc/ticket/8516#8516: Add (->) representation and the Invariant class to GHC.GenericsSat, 09 Nov 2013 20:39:41 GMTnfrisby<p>
We currently disallow any use of the parameter in the domain of (->).
</p>
<pre class="wiki">newtype F a = F ((a -> Int) -> Int) deriving Generic1
<interactive>:4:38:
Can't make a derived instance of `Generic1 (F g)':
Constructor `F' must use the last type parameter only as the last argument of a data type, newtype, or (->)
In the data declaration for `F'
</pre><p>
DeriveFunctor succeeds for this F.
</p>
<p>
I'd like to add this representation type to GHC.Generics and DeriveGeneric.
</p>
<pre class="wiki">newtype (f :->: g) a = FArrow1 (f a -> g a)
</pre><p>
We could then represent the first example above. We could also derive the more interesting Generic1 (F g).
</p>
<pre class="wiki">newtype F g a = F (g a -> Int) deriving Generic1
type instance Rep1 (F g) = Rec1 g :->: Rec0 Int
instance Generic1 (F g) where
to x = F $ unRec0 . unArrow1 x . Rec1
from (F x) = FArrow1 $ Rec0 . x . unRec1
</pre><p>
Admittedly, there's not many generic definitions impeded by not having (:->:). Contra- and in-variant types are uncommon.
</p>
<p>
I'm suggesting this feature without strong motivating examples because I think this would streamline the implementation of -XDeriveGenerics in some ways while also making it more general — assuming that we added the Invariant class to base or ghc-prim.
</p>
<pre class="wiki">class Invariant t where
invmap :: (a -> b) -> (b -> a) -> t a -> t b
invmap_covariant :: Functor t => (a -> b) -> (b -> a) -> t a -> t b
invmap_covariant f _ = fmap f
instance (Invariant f,Invariant g) => Invariant (FArrow f g) where
invmap co contra (FArrow h) = FArrow $ invmap co contra . h . invmap contra co
</pre><p>
(Of course, Invariant should be a super class of Functor. :/ )
</p>
<p>
Now we can handle quite involved examples:
</p>
<pre class="wiki">newtype F g h a = F (g (h a)) deriving Generic1
instance Invariant g => Generic1 (F g h) where
to x = invmap unRec1 Rec1 $ unComp1 x
from (F x) = Comp1 $ invmap Rec1 unRec1
</pre><p>
All of that said, I'm mostly opening this ticket so I can get feedback on difficulties I might not be anticipating and have a place to reference from the compiler source code comments.
</p>
Resultshttp://ghc.haskell.org/trac/ghc/ticket/8516#changelog