diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2011-08-16 10:23:52 +0100 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2011-08-16 10:23:52 +0100 |
commit | 49dbe60558deee5ea6cd2c7730b7c591d15559c8 (patch) | |
tree | 42dcc755858d60ce2b521a308016b4ff6e34d864 /compiler/rename | |
parent | 20ceffb6505f3a148edc9150f5f07584f945ab95 (diff) | |
download | haskell-49dbe60558deee5ea6cd2c7730b7c591d15559c8.tar.gz |
Major improvement to pattern bindings
This patch makes a number of related improvements
a) Implements the Haskell Prime semantics for pattern bindings
(Trac #2357). That is, a pattern binding p = e is typed
just as if it had been written
t = e
f = case t of p -> f
g = case t of p -> g
... etc ...
where f,g are the variables bound by p. In paricular it's
ok to say
(f,g) = (\x -> x, \y -> True)
and f and g will get propertly inferred types
f :: a -> a
g :: a -> Int
b) Eliminates the MonoPatBinds flag altogether. (For the moment
it is deprecated and has no effect.) Pattern bindings are now
generalised as per (a). Fixes Trac #2187 and #4940, in the
way the users wanted!
c) Improves the OutsideIn algorithm generalisation decision.
Given a definition without a type signature (implying "infer
the type"), the published algorithm rule is this:
- generalise *top-level* functions, and
- do not generalise *nested* functions
The new rule is
- generalise a binding whose free variables have
Guaranteed Closed Types
- do not generalise other bindings
Generally, a top-level let-bound function has a Guaranteed
Closed Type, and so does a nested function whose free vaiables
are top-level functions, and so on. (However a top-level
function that is bitten by the Monomorphism Restriction does
not have a GCT.)
Example:
f x = let { foo y = y } in ...
Here 'foo' has no free variables, so it is generalised despite
being nested.
d) When inferring a type f :: ty for a definition f = e, check that
the compiler would accept f :: ty as a type signature for that
same definition. The type is rejected precisely when the type
is ambiguous.
Example:
class Wob a b where
to :: a -> b
from :: b -> a
foo x = [x, to (from x)]
GHC 7.0 would infer the ambiguous type
foo :: forall a b. Wob a b => b -> [b]
but that type would give an error whenever it is called; and
GHC 7.0 would reject that signature if given by the
programmer. The new type checker rejects it up front.
Similarly, with the advent of type families, ambiguous types are
easy to write by mistake. See Trac #1897 and linked tickets for
many examples. Eg
type family F a :: *
f ::: F a -> Int
f x = 3
This is rejected because (F a ~ F b) does not imply a~b. Previously
GHC would *infer* the above type for f, but was unable to check it.
Now even the inferred type is rejected -- correctly.
The main implemenation mechanism is to generalise the abe_wrap
field of ABExport (in HsBinds), from [TyVar] to HsWrapper. This
beautiful generalisation turned out to make everything work nicely
with minimal programming effort. All the work was fiddling around
the edges; the core change was easy!
Diffstat (limited to 'compiler/rename')
-rw-r--r-- | compiler/rename/RnBinds.lhs | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/compiler/rename/RnBinds.lhs b/compiler/rename/RnBinds.lhs index 2a1330370a..a833c83b01 100644 --- a/compiler/rename/RnBinds.lhs +++ b/compiler/rename/RnBinds.lhs @@ -334,8 +334,10 @@ rnLocalValBindsRHS :: NameSet -- names bound by the LHSes rnLocalValBindsRHS bound_names binds = rnValBindsRHS trim (Just bound_names) binds where - trim fvs = intersectNameSet bound_names fvs - -- Only keep the names the names from this group + trim fvs = filterNameSet isInternalName fvs + -- Keep Internal Names; these are the non-top-level ones + -- As well as dependency analysis, we need these for the + -- MonoLocalBinds test in TcBinds.decideGeneralisationPlan -- for local binds -- wrapper that does both the left- and right-hand sides |