[GHC] #11243: Flag to not expand type families
GHC
ghc-devs at haskell.org
Fri Dec 18 11:49:30 UTC 2015
#11243: Flag to not expand type families
-------------------------------------+-------------------------------------
Reporter: crockeea | Owner:
Type: feature request | Status: new
Priority: normal | Milestone: 8.2.1
Component: Compiler | Version: 7.10.2
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by simonpj):
The underlying issue is this:
* Suppose `F` is a type function with an instance for `F [Int]`. If we
have constraints
1. `(C (F [Int]))`, where `C` is a class
2. `F [Int] ~ Maybe Bool`
3. `G (F [Int]) ~ Maybe Bool`
then we want to apply the instance in case that unlocks the class
constraint or equality.
* That expansion may be fruitless. For (1), perhaps `F [Int]` expands to
`Bool`, `C` has no `Bool` instance. Then would you prefer to see "can't
solve `C (F [Int])`" or "can't solve `C Bool`? Perhaps the latter.
* In (3) we might expand `F [Int]` vigorously to get a big type, and
''still'' not be able to simplify the call to `G`.
In the case of type synonyms we can have the best of both worlds. Say we
have
{{{
type T a = S a a
}}}
Then the type `T [Int]` is represented (essentially) as a pair of its
expanded and un-expanded form;
so we can freely choose to use either at any time.
But it's not so easy for type functions becuase the expanded and un-
expanded forms are not
interchangeable; there's a coercion involved.
I think we could still be a bit less aggressive about expansion. We even
implemted this once. But we disabled it for ill-understood performance
reasons.
Here is the Note from `TcFlatten`:
{{{
Note [Lazy flattening]
~~~~~~~~~~~~~~~~~~~~~~
The idea of FM_Avoid mode is to flatten less aggressively. If we have
a ~ [F Int]
there seems to be no great merit in lifting out (F Int). But if it was
a ~ [G a Int]
then we *do* want to lift it out, in case (G a Int) reduces to Bool, say,
which gets rid of the occurs-check problem. (For the flat_top Bool, see
comments above and at call sites.)
HOWEVER, the lazy flattening actually seems to make type inference go
*slower*, not faster. perf/compiler/T3064 is a case in point; it gets
*dramatically* worse with FM_Avoid. I think it may be because
floating the types out means we normalise them, and that often makes
them smaller and perhaps allows more re-use of previously solved
goals. But to be honest I'm not absolutely certain, so I am leaving
FM_Avoid in the code base. What I'm removing is the unique place
where it is *used*, namely in TcCanonical.canEqTyVar.
See also Note [Conservative unification check] in TcUnify, which gives
other examples where lazy flattening caused problems.
Bottom line: FM_Avoid is unused for now (Nov 14).
Note: T5321Fun got faster when I disabled FM_Avoid
T5837 did too, but it's pathalogical anyway
}}}
In short, here's a project for someone!
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11243#comment:12>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list