Re: DoCon and GHC

On Wed, Jan 02, 2013 at 05:21:43PM +0000, Simon Peyton-Jones wrote:
Serge
That's odd. I've tried with both 7.6 and HEAD, and both fail on T_cubeext thus: T_cubeext.hs:102:10: Overlapping instances for LinSolvRing (UPol k) arising from a use of `upEucRing' Matching instances: instance [overlap ok] EuclideanRing a => LinSolvRing (UPol a) -- Defined in `docon-2.12:Pol2_' instance [overlap ok] (LinSolvRing (Pol a), CommutativeRing a) => LinSolvRing (UPol (Pol a)) -- Defined in `docon-2.12:Pol3_' (The choice depends on the instantiation of `k' To pick the first instance above, use -XIncoherentInstances when compiling the other instance declarations) In the expression: upEucRing unA Map.empty In an equation for `dA': dA = upEucRing unA Map.empty
I am using ghc-7.6 from Dec 3 (ie *later* than the released GHC 7.6.1), so perhaps the difference in error message is due to a bug in 7.6.1 that's fixed in my version. I suggest you use the 7.6.2 release candidate.
Yes, the candidate of 7.6.1.20121207
Anyway, the error message looks entirely legitimate. It really does matter how 'k' is instantiated! I have no idea how it compiled before.
ghc-7.4.1 compiles everything in DoCon, and it is the last such version.
The solution is to add (EuclideanRing k) to the type sig of cubicExt. Then it compiles all the way up to the top.
But the DoCon declares class (EuclideanRing a, FactorizationRing a) => Field a (EuclideanRing is a superclass for Field), and the test declares cubicExt :: (Field k, FactorizationRing (UPol k)) => k -> k -> Domains1 k -> (Domains1 (E k), [E k], k -> E k) So, why the compiler does not `extract' EuclideanRing k from Field k ? Regards, ------ Sergei
| -----Original Message----- | From: glasgow-haskell-bugs-bounces@haskell.org [mailto:glasgow-haskell- | bugs-bounces@haskell.org] On Behalf Of Serge D. Mechveliani | Sent: 21 December 2012 18:46 | To: Simon Peyton-Jones | Cc: glasgow-haskell-bugs@haskell.org | Subject: Re: DoCon and GHC | | On Fri, Dec 21, 2012 at 01:45:04PM +0000, Simon Peyton-Jones wrote: | > OK, do this | > | > * {-# LANGUAGE ScopedTypeVariables, MonoLocalBinds #-} | > | > * import Categs( Domains1 ) | > | > * Add type sig for dP' | > dP' :: (LinSolvRing (Pol a), CommutativeRing a) => Domains1 (Pol | > a) | > | > Then it compiles. | > | > You are very close to the edge of what can be done! | | | It works. Thank you. | | There remains only a single unlucky module: T_cubeext. | The test demotest/Main works with exception of T_cubeext, but I need | T_cubeext.cubicExt to work. | | Please, continue the test with | | make install | cd demotest | ghc $doconCpOpt --make Main | | (for $doconCpOpt = | -fwarn-unused-matches -fwarn-unused-binds -fwarn-unused-imports | -fno-warn-overlapping-patterns -XRecordWildCards -XNamedFieldPuns | -XFlexibleContexts -XMultiParamTypeClasses -XUndecidableInstances | -XTypeSynonymInstances -XFlexibleInstances -XOverlappingInstances ). | | It reports | | ------------------------------------------------------------------ | ... | T_cubeext.hs:102:20: | Could not deduce (k ~ k1) | from the context (Field k, FactorizationRing (UPol k)) | bound by the type signature for | cubicExt :: (Field k, FactorizationRing (UPol k)) => | k -> k -> Domains1 k -> (Domains1 (E k), [E | k], k -> E k) | at T_cubeext.hs:(79,13)-(80,69) | or from (Field k1, FactorizationRing (UPol k1)) | bound by the type signature for | unA :: (Field k1, FactorizationRing (UPol k1)) => UPol | k1 | at T_cubeext.hs:101:9-56 | `k' is a rigid type variable bound by | the type signature for | cubicExt :: (Field k, FactorizationRing (UPol k)) => | k -> k -> Domains1 k -> (Domains1 (E k), [E k], | k -> E k) | at T_cubeext.hs:79:13 | `k1' is a rigid type variable bound by | the type signature for | unA :: (Field k1, FactorizationRing (UPol k1)) => UPol k1 | at T_cubeext.hs:101:9 | Expected type: Domains1 k1 | Actual type: Domains1 k | In the second argument of `cToUPol', namely `dK' | In the expression: cToUPol "d" dK unK | In an equation for `unA': unA = cToUPol "d" dK unK | | T_cubeext.hs:105:7: | Overlapping instances for LinSolvRing (UPol k1) | arising from a use of `upEucRing' | Matching instances: | instance [overlap ok] EuclideanRing a => LinSolvRing (UPol a) | -- Defined in `docon-2.12:Pol2_' | instance [overlap ok] (LinSolvRing (Pol a), CommutativeRing a) => | LinSolvRing (UPol (Pol a)) ... | ------------------------------------------------------------------ | | I tried {-# LANGUAGE ScopedTypeVariables, MonoLocalBinds #-}, and | setting type signatures in various parts in cubicExt. | But this does not help. | | There is another point. In | ``cubicExt :: (Field k, FactorizationRing (UPol k)) => ...'' | | the part ``, FactorizationRing (UPol k)'' (1) | | was always considered as parasitic. ghc-7.4.1 needs (1) to work, and | at least ghc-7.4.1 does compile the test. | | I thought, may be, the future compilers will allow to omit this part. | At least it is desirable for ghc-7.6.2 to do the test in any variant, | with (1) or without it.

| > The solution is to add (EuclideanRing k) to the type sig of cubicExt. | > Then it compiles all the way up to the top. | | But the DoCon declares | class (EuclideanRing a, FactorizationRing a) => Field a | | (EuclideanRing is a superclass for Field), | and the test declares | cubicExt :: (Field k, FactorizationRing (UPol k)) => | k -> k -> Domains1 k -> (Domains1 (E k), [E k], k -> E k) | | So, why the compiler does not `extract' EuclideanRing k from Field k I made a mistake. I should have said "add (EuclideanRing (Pol k)) to the type sig of cubicExt". GHC can't extract EuclideanRing (Pol k) from Field k except by using one of the two (overlapping) instances. I don't know why 7.4 accepts it, but I'm not inclined to investigate... looks like a bug in 7.4. Simon

On Wed, Jan 02, 2013 at 08:23:37PM +0000, Simon Peyton-Jones wrote:
| > The solution is to add (EuclideanRing k) to the type sig of cubicExt. | > Then it compiles all the way up to the top. | | But the DoCon declares | class (EuclideanRing a, FactorizationRing a) => Field a | | (EuclideanRing is a superclass for Field), | and the test declares | cubicExt :: (Field k, FactorizationRing (UPol k)) => | k -> k -> Domains1 k -> (Domains1 (E k), [E k], k -> E k) | | So, why the compiler does not `extract' EuclideanRing k from Field k
I made a mistake. I should have said "add (EuclideanRing (Pol k)) to the type sig of cubicExt".
GHC can't extract EuclideanRing (Pol k) from Field k except by using one of the two (overlapping) instances.
I don't know why 7.4 accepts it, but I'm not inclined to investigate... looks like a bug in 7.4.
ghc-7.4.1 may use a special trick, but is correct.
I should have said "add (EuclideanRing (Pol k)) to the type sig of cubicExt".
(1) UPol is for an Univariate Polynomial, and Pol is for an Multivariate Polynomial (more generic). (2) DoCon declares Field k => EuclideanRing (UPol k). (3) DoCon does not have the instance Field k => EuclideanRing (Pol k), because it is not correct in algebra. Haskell+Glasgow can not derive EuclideanRing (Pol k) from Field k in the DoCon code. (4) In cubicExt, Haskell+Glasgow derives a weaker instances: LinSolvRing (Pol k), LinSolvRing (Pol (UPol k)), LinSolvRing (UPol (Pol k)) -- and this is sufficient. This is the intension of DoCon + cubicExt, and ghc-7.4.1 supports this (may be, by some tricky designп, I do not know). (5) I can add EuclideanRing (UPol k) to the sig of cubicExt (even though Haskell+Glasgow must derive it), but I expect that this would not help. (6) I can not add EuclideanRing (Pol k) to the sig of cubicExt, because this is not correct by the algebraic design. cubicExt indeed uses rather a complicated set of instances. I do not know, may be I need to think of how to reorganize the design for porting it to ghc-7.6.2. ghc-7.4.1 did the job correctly, and it is difficult to change the coresponding part of the DoCon design. And if you happen to find how to meet (1) -- (6), then I would not need to re-design the thing. Regards, ------ Sergei

I made a second mistake. I meant (LinSolvRing (UPol k)). Apologies. | > I don't know why 7.4 accepts it, but I'm not inclined to investigate... | > looks like a bug in 7.4. | | ghc-7.4.1 may use a special trick, but is correct. I don't understand your explanation. What is wrong with this reasoning? 1. The call to upEucRing in cubicExt gives rise the constraint (LinSolvRing (UPol k)) Corect? 2. There are two overlapping instances for (LinSolvRing (UPol k)), defined in UPol2_ and UPol3_ Correct? 3. So GHC cannot solve the constraint using an instance declaration. Correct? 4. The type signature provides (Field k, FactorizationRing (UPol k)) but neither is enough to satisfy LinSolvRing (UPol k). Correct? 5. Therefore we must add LinSolvRing (UPol k) to the signature. If you believe that the function should typecheck as-is, please explain how to deduce (LinSolvRing (UPol k)) from (Field k, FactorizationRing (UPol k)). Simon

On Wed, Jan 02, 2013 at 11:27:15PM +0000, Simon Peyton-Jones wrote:
I made a second mistake. I meant (LinSolvRing (UPol k)). Apologies.
| > I don't know why 7.4 accepts it, but I'm not inclined to investigate... | > looks like a bug in 7.4. | | ghc-7.4.1 may use a special trick, but is correct.
I don't understand your explanation. What is wrong with this reasoning?
1. The call to upEucRing in cubicExt gives rise the constraint (LinSolvRing (UPol k)) Corect?
2. There are two overlapping instances for (LinSolvRing (UPol k)), defined in UPol2_ and UPol3_ Correct?
3. So GHC cannot solve the constraint using an instance declaration. Correct?
4. The type signature provides (Field k, FactorizationRing (UPol k)) but neither is enough to satisfy LinSolvRing (UPol k). Correct?
5. Therefore we must add LinSolvRing (UPol k) to the signature.
If you believe that the function should typecheck as-is, please explain how to deduce (LinSolvRing (UPol k)) from (Field k, FactorizationRing (UPol k)).
1. I try adding `, LinSolvRing (UPol k)' to the sig of cubeExt. Now, ghc-7.6.1.20121207 builds docon-2.12 but does not compile the demonstration of T_cubeext.hs (where cubicExt is) -- with {-# LANGUAGE ScopedTypeVariables, MonoLocalBinds #-} prepended to the module. Can you, please, reproduce this in ghc-7.6.1.20121207 ? Because a) the problem is in porting to a fresh stable GHC version, b) ghc-7.6.1.20121207 is announced to become a fresh ghc-7.6.2, and it asks for testing, c) if I use an older version, then, why, I could simply remain with ghc-7.4.1. 2. Now suppose that a fresh GHC is fixed, and the point (1) works. Adding `, LinSolvRing (UPol k)' is not an error. But is an awkward algebraic statement. For example, one can formulate "for all integer p > 2 such that p is prime and p is odd, it holds Foo(p)". Adding "and p is odd" is not an error, but looks awkward, because it is derived from (p > 2, p is prime) according to previous theory. This reduces redability of the text, because the reader starts to think that he is missing something subtle. Similarly, LinSolvRing (UPol k) is derived in cubicExt from cubicExt and from the proper DoCon. The matter is that the algorithm (instance) for this LinSolvRing (UPol k) is derived in multiple ways -- overlapping instances. 3. For this particular case, I agree to tell to GHC: "choose any derivation way you like". Because a) I know that the needed final result part does not depend on this choice (even though the algoritms differ), b) the cost difference will not be great. How can I tell this to GHC -- with respect to only this function signature, or maybe, only to this module ? 4. Probably, the rule of the substitutional instance specialization in Haskell+Glasgow is not enough to follow algebra. Why not give the user an additional way to choose the derivation? For example, let there be the instances I, II, III, IV, and the instance (Foo T) is derived from I, II, III, IV in multiple ways. The programmer writes the signature f :: (..., (Foo T, using {II, III}, notUsing {I, IV})) => ... which means to consider for (Foo T) only those derivations which use {II, III} and do not use {I, IV}. I do not know, may be I am missing something. 5. Now, I specify how LinSolvRing (UPol k) is derived in the existing Haskell+Glasgow language. DoCon = Proper-DoCon + demo; cubicExt is a part of demo. First, Proper-DoCon is installed -- this works. And cubicExt is not compiled. Proper-DoCon includes: GCDRing a and EuclideanRing a are superclasses for Field a, (I) class (GCDRing a, LinSolvRing a) => EuclideanRing a where ... (II) instance GCDRing a => GCDRing (UPol a) where ... (III) instance Field k => EuclideanRing (UPol k) where ... (IV) instance EuclideanRing a => LinSolvRing (UPol a) where ... (V) (in Pol2_.hs) Each of these has a very useful algebraic meaning. Now, GHC starts to compile cubicExt. And there Field k => LinSolvRing (UPol k) is derived from I -- V in at least two ways, and may be there are even more of them. Algebraically, these overlaps are all right, they are in the nature, these derivations give equivalent results. But one may insist: "choose the way, because the algorithms are different, and the computation cost may differ". For example, for Field k => LinSolvRing (UPol k), I would choose this way: "Field k is declared. Euclidean is a superclass for Field by (I). hence there is the instance Euclidean k. hence there is the instance LinSolvRing (UPol k) by V with a := k. " And Haskell+Glasgow sees this derivation surely. In the algebra textbooks it is expressed like this: "k is a Field, hence it is EuclideanRing, hence, by V, (UPol k) is LinSolvRing." Other ways I consider as algorithmically parasitic. They appear by GHC composing I -- V in various combinations. I am forced to write I -- V, because each of them is useful by itself in various situations; this is in the nature of algebra. On the other hand, I have not enough language constructs to cut out (for GHC) the combinations that are parasitic -- with respect to the computational cost choice. Here is another derivation for Field k => LinSolvRing (UPol k). Repeat the state: GCDRing a and EuclideanRing a are superclasses for Field a, (I) class (GCDRing a, LinSolvRing a) => EuclideanRing a where ... (II) instance GCDRing a => GCDRing (UPol a) (III) instance Field k => EuclideanRing (UPol k) (IV) instance EuclideanRing a => LinSolvRing (UPol a) (V) (in Pol2_.hs) The derivation is: Field k is given. EuclideanRing (UPol k) is by IV. LinSolvRing a is a superclass for EuclideanRing a by II. Hence, with a := UPol k, there must presense the instance LinSolvRing (UPol k), such an instance must precede IV in order IV to be compiled. And GHC finds the instance for LinSolvRing (UPol k). For example, it is by V with a := k. And it occurs that the first derivation is a part of the second one. I do not know how many derivations exist, and whether GHC ignores the second one. But at least I have answered to the question
If you believe that the function should typecheck as-is, please explain how to deduce (LinSolvRing (UPol k)) from (Field k, FactorizationRing (UPol k)).
I have presented the two derivations, the first one looks natural.
I don't understand your explanation. What is wrong with this reasoning?
1. The call to upEucRing in cubicExt gives rise the constraint (LinSolvRing (UPol k)) Corect?
Yes. It gives rise to EuclideanRing (UPol k). And LinSolvRing a is a superclass for EuclideanRing a. And the constraint of EuclideanRing (UPol k) follows from the call to upEucRing in cubicExt and from the declaration upEucRing :: EuclideanRing a => ADomDom a in Ring_0.hs. Because cubicExt applies upEucRing with a = (Field k, ...) => UPol k The condition of EuclideanRing (UPol k) is satisfied by the following declarations in DoCon (not in the demonstration program): GCDRing a and EuclideanRing a are superclasses for Field a, (I) class (GCDRing a, LinSolvRing a) => EuclideanRing a (II) instance GCDRing a => GCDRing (UPol a) (III) instance Field k => EuclideanRing (UPol k) (IV) instance EuclideanRing a => LinSolvRing (UPol a) (V) (in Pol2_.hs) So, Field k => EuclideanRing (UPol k) follows by IV and also by V & III & I (I find this way only now).
2. There are two overlapping instances for (LinSolvRing (UPol k)), defined in UPol2_ and UPol3_ Correct?
a) DoCon has not UPol2_.hs nor UPol3_.hs. It has Pol2_.hs and Pol3_.hs. (And for any occasion: as I wrote earlier, the data costructors Pol and UPol have different meaning and different instance sets ). b) I have shown the two derivations for Field k => LinSolvRing (UPol k) (the second one in strange, because it is included in the first). May be, there exists some more clear overlap. instance EuclideanRing a => LinSolvRing (UPol a) of Pol_2.hs is used in the first derivation. c) Pol3_ has instance (LinSolvRing (Pol a), CommutativeRing a) => LinSolvRing (UPol (Pol a)) But this does not overlap with I -- V, in particular, not with Field k => LinSolvRing (UPol k). Because Pol a is never of a Field nor of EuclideanRing. And Hashell+Glasgow sees this.
3. So GHC cannot solve the constraint using an instance declaration. Correct?
GHC finds multiple solutions for this constraint. Several instances overlap. Each of these derivations is algebraically correct. I do not know of whether this overlap is resolved by the rules of the Haskell+Glasgow language. Also ghc-7.4.1 says it resolves them (at least, the demo program works correct), and ghc-7.6.1.20121207 does not resolve.
4. The type signature provides (Field k, FactorizationRing (UPol k)) but neither is enough to satisfy LinSolvRing (UPol k). Correct?
No. LinSolvRing (UPol k) is derived by Haskell+Glasgow from Field k. See above my explanation. But it is derived in multiple ways.
5. Therefore we must add LinSolvRing (UPol k) to the signature.
This is not an error. But ghc-7.6.1.20121207 does not compile this. Also see the beginning of my part of this letter.
If you believe that the function should typecheck as-is, please explain how to deduce (LinSolvRing (UPol k)) from (Field k, FactorizationRing (UPol k)).
I have shown this above. The GHC problem is that most probably, it is deduced in multiple ways. At least, it is now desirable the following: to make ghc-7.6.1.20121207 to compile your variant with adding LinSolvRing (UPol k) to the signature. Do you agree with this single point? Regards, ------ Sergei

OK I have tested with today's GHC 7.6.2, which is very slightly later than the release candidate. When I add (EuclideanRing (UPol k)) to the signature for cubicExt, the whole of demotest compiles. So that works. Your misconception is here: | c) Pol3_ has | instance (LinSolvRing (Pol a), CommutativeRing a) => | LinSolvRing (UPol (Pol a)) | But this does not overlap with Field k => LinSolvRing (UPol k). | | Because Pol a is never of a Field nor of EuclideanRing. When matching instances, GHC does not take account of the context of the instance. Say you have data T a = ... data S1 = ... data S2 = ... [a] instance Num a => Num (T a) where ... [b] instance Show a => Num (T a) where ... instance Num S1 and suppose you need an instance of (Num (T S1)). Then although [a] and [b] overlap, you might say we should use [a], since S1 is an instance of Num, but not an instance of Show. But GHC does not do this. It matches instances only based on the bit after the "=>". I'm sorry, but that's the way it is. (There are good reasons for this.) If you don't care which of the overlapping instances is picked, then you can use -XIncoherentInstances. But you have to set that flag at the *instance declaration* not at the *use* of the instance. In this case it would be the instance for LinSolvRing (UPol k) Simon

On Thu, Jan 3, 2013 at 4:57 AM, Simon Peyton-Jones
When matching instances, GHC does not take account of the context of the instance. Say you have
data T a = ... data S1 = ... data S2 = ... [a] instance Num a => Num (T a) where ... [b] instance Show a => Num (T a) where ... instance Num S1
and suppose you need an instance of (Num (T S1)). Then although [a] and [b] overlap, you might say we should use [a], since S1 is an instance of Num, but not an instance of Show. But GHC does not do this. It matches instances only based on the bit after the "=>".
It seems you're making GHC seem more capricious than it is here. Even were GHC to consider contexts in instance selection, the choice of [a] over [b] would still be incoherent: the compiler has no way to prove that there is no later instance adding S1 to class Show. Indeed, the S1's and S2's are in some sense not relevant: because Haskell provides no mechanism to exclude types from classes, there is no way to ever coherently use instance [a] or [b], regardless of the argument to T. /g -- Sent from my mail client.

This is copying to the list my reply to Simon: On Thu, Jan 03, 2013 at 12:57:02PM +0000, Simon Peyton-Jones wrote:
OK I have tested with today's GHC 7.6.2, which is very slightly later than the release candidate.
When I add (EuclideanRing (UPol k)) to the signature for cubicExt, the whole of demotest compiles. So that works.
Also ghc $doconCpOpt --make Main ./Main must end with "No errors detected", and take not more than 4 sec on a 2 GHz machine (for suppose that an overlap is resolved unluckily for the cost, so that the time becomes, say 60 sec).
Your misconception is here:
| c) Pol3_ has | instance (LinSolvRing (Pol a), CommutativeRing a) => | LinSolvRing (UPol (Pol a)) | But this does not overlap with Field k => LinSolvRing (UPol k). | | Because Pol a is never of a Field nor of EuclideanRing.
When matching instances, GHC does not take account of the context of the instance. Say you have [..]
I knew this, and have forgotten. Thank you.
If you don't care which of the overlapping instances is picked, then you can use -XIncoherentInstances. But you have to set that flag at the *instance declaration* not at the *use* of the instance. In this case it would be the instance for LinSolvRing (UPol k)
Probably, this will work good in one place where this instance is used, and work bad in another place. In the papers on algorithmic algebra the authors often compute some foo for a domain T, and consider various methods for this computation, and often a method is defined by the choice of the instance derivation. And the author writes: apply the method defined by this and this instance construction, this costs, say, O(n^3) bit operations, and so on (literally, the word `instance' is not written). So, there is not a problem of specifying the overlap resolving in papers and lectures, this is done easily. But Haskell+Glasgow does not provide a sufficient language construct for such a resolving. It has the rule of a "substitutionally more special instance". Probably, something appropriate can be added to this rule. Anyway, I shall wait for ghc-7.6.2, and see. Thanks, ------ Sergei
participants (3)
-
J. Garrett Morris
-
Serge D. Mechveliani
-
Simon Peyton-Jones