summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2014-11-11 10:27:51 +0000
committerSimon Peyton Jones <simonpj@microsoft.com>2014-11-11 10:28:20 +0000
commit97420b053a3d05a347a5ce38978252bd5ad2f854 (patch)
tree5828e0a735484d8146bf78654ff070e1b33a4736
parente56713024e1bfbb7892986800afd9944731b2aa1 (diff)
downloadhaskell-97420b053a3d05a347a5ce38978252bd5ad2f854.tar.gz
Comments only (on recursive dictionaries)
-rw-r--r--compiler/typecheck/TcInstDcls.lhs15
-rw-r--r--compiler/typecheck/TcInteract.lhs83
2 files changed, 58 insertions, 40 deletions
diff --git a/compiler/typecheck/TcInstDcls.lhs b/compiler/typecheck/TcInstDcls.lhs
index ddb2e6531a..b6c0da1e8b 100644
--- a/compiler/typecheck/TcInstDcls.lhs
+++ b/compiler/typecheck/TcInstDcls.lhs
@@ -1009,23 +1009,28 @@ superclass is bottom when it should not be.
Consider the following (extreme) situation:
class C a => D a where ...
- instance D [a] => D [a] where ...
+ instance D [a] => D [a] where ... (dfunD)
+ instance C [a] => C [a] where ... (dfunC)
Although this looks wrong (assume D [a] to prove D [a]), it is only a
more extreme case of what happens with recursive dictionaries, and it
can, just about, make sense because the methods do some work before
recursing.
-To implement the dfun we must generate code for the superclass C [a],
+To implement the dfunD we must generate code for the superclass C [a],
which we had better not get by superclass selection from the supplied
argument:
- dfun :: forall a. D [a] -> D [a]
- dfun = \d::D [a] -> MkD (scsel d) ..
+ dfunD :: forall a. D [a] -> D [a]
+ dfunD = \d::D [a] -> MkD (scsel d) ..
Otherwise if we later encounter a situation where
we have a [Wanted] dw::D [a] we might solve it thus:
- dw := dfun dw
+ dw := dfunD dw
Which is all fine except that now ** the superclass C is bottom **!
+The instance we want is:
+ dfunD :: forall a. D [a] -> D [a]
+ dfunD = \d::D [a] -> MkD (dfunC (scsel d)) ...
+
THE SOLUTION
Our solution to this problem "silent superclass arguments". We pass
diff --git a/compiler/typecheck/TcInteract.lhs b/compiler/typecheck/TcInteract.lhs
index 6fbed77e05..3501a99e12 100644
--- a/compiler/typecheck/TcInteract.lhs
+++ b/compiler/typecheck/TcInteract.lhs
@@ -1087,56 +1087,69 @@ Consider generating the superclasses of the instance declaration
instance Foo a => Foo [a]
So our problem is this
- d0 :_g Foo t
- d1 :_w Data Maybe [t]
+ [G] d0 : Foo t
+ [W] d1 : Data Maybe [t] -- Desired superclass
We may add the given in the inert set, along with its superclasses
[assuming we don't fail because there is a matching instance, see
topReactionsStage, given case ]
Inert:
- d0 :_g Foo t
+ [G] d0 : Foo t
+ [G] d01 : Data Maybe t -- Superclass of d0
WorkList
- d01 :_g Data Maybe t -- d2 := EvDictSuperClass d0 0
- d1 :_w Data Maybe [t]
-Then d2 can readily enter the inert, and we also do solving of the wanted
+ [W] d1 : Data Maybe [t]
+
+Solve d1 using instance dfunData2; d1 := dfunData2 d2 d3
Inert:
- d0 :_g Foo t
- d1 :_s Data Maybe [t] d1 := dfunData2 d2 d3
+ [G] d0 : Foo t
+ [G] d01 : Data Maybe t -- Superclass of d0
+ Solved:
+ d1 : Data Maybe [t]
WorkList
- d2 :_w Sat (Maybe [t])
- d3 :_w Data Maybe t
- d01 :_g Data Maybe t
-Now, we may simplify d2 more:
+ [W] d2 : Sat (Maybe [t])
+ [W] d3 : Data Maybe t
+
+Now, we may simplify d2 using dfunSat; d2 := dfunSat d4
Inert:
- d0 :_g Foo t
- d1 :_s Data Maybe [t] d1 := dfunData2 d2 d3
- d1 :_g Data Maybe [t]
- d2 :_g Sat (Maybe [t]) d2 := dfunSat d4
+ [G] d0 : Foo t
+ [G] d01 : Data Maybe t -- Superclass of d0
+ Solved:
+ d1 : Data Maybe [t]
+ d2 : Sat (Maybe [t])
WorkList:
- d3 :_w Data Maybe t
- d4 :_w Foo [t]
- d01 :_g Data Maybe t
+ [W] d3 : Data Maybe t
+ [W] d4 : Foo [t]
-Now, we can just solve d3.
+Now, we can just solve d3 from d01; d3 := d01
Inert
- d0 :_g Foo t
- d1 :_s Data Maybe [t] d1 := dfunData2 d2 d3
- d2 :_g Sat (Maybe [t]) d2 := dfunSat d4
+ [G] d0 : Foo t
+ [G] d01 : Data Maybe t -- Superclass of d0
+ Solved:
+ d1 : Data Maybe [t]
+ d2 : Sat (Maybe [t])
WorkList
- d4 :_w Foo [t]
- d01 :_g Data Maybe t
-And now we can simplify d4 again, but since it has superclasses we *add* them to the worklist:
+ [W] d4 : Foo [t]
+
+Now, solve d4 using dfunFoo2; d4 := dfunFoo2 d5
Inert
- d0 :_g Foo t
- d1 :_s Data Maybe [t] d1 := dfunData2 d2 d3
- d2 :_g Sat (Maybe [t]) d2 := dfunSat d4
- d4 :_g Foo [t] d4 := dfunFoo2 d5
+ [G] d0 : Foo t
+ [G] d01 : Data Maybe t -- Superclass of d0
+ Solved:
+ d1 : Data Maybe [t]
+ d2 : Sat (Maybe [t])
+ d4 : Foo [t]
WorkList:
- d5 :_w Foo t
- d6 :_g Data Maybe [t] d6 := EvDictSuperClass d4 0
- d01 :_g Data Maybe t
-Now, d5 can be solved! (and its superclass enter scope)
- Inert
+ [W] d5 : Foo t
+
+Now, d5 can be solved! d5 := d0
+
+Result
+ d1 := dfunData2 d2 d3
+ d2 := dfunSat d4
+ d3 := d01
+ d4 := dfunFoo2 d5
+ d5 := d0
+
d0 :_g Foo t
d1 :_s Data Maybe [t] d1 := dfunData2 d2 d3
d2 :_g Sat (Maybe [t]) d2 := dfunSat d4