
Am Donnerstag 17 September 2009 18:01:36 schrieb Andy Gimblett:
On 17 Sep 2009, at 16:50, Daniel Fischer wrote:
Yes, the second appearance of 'constructors' is at an unspecified type.
instance (Enumerated a) => Target a where convert n
| n < 0 = Nothing | otherwise = case drop n constructors of
(x:_) -> Just x _ -> Nothing
would make it compile.
Neat trick. It works: thanks!
But there'd be a risk that Target is unusable, depending on how instance resolution is done.
Unusable? How so? Sorry, but I don't follow...
Cf. Section 7.6.3.3 of the user's guide: "When matching, GHC takes no account of the context of the instance declaration (context1 etc). GHC's default behaviour is that exactly one instance must match the constraint it is trying to resolve. It is fine for there to be a potential of overlap (by including both declarations (A) and (B), say); an error is only reported if a particular constraint matches more than one. The -XOverlappingInstances flag instructs GHC to allow more than one instance to match, provided there is a most specific one. For example, the constraint C Int [Int] matches instances (A), (C) and (D), but the last is more specific, and hence is chosen. If there is no most-specific match, the program is rejected." So for the matching, you have now instance Target a where ... which matches everything. Add an instance declaration of the form instance (SomeClass b) => Target b where ... and you're hosed. Though I think that wouldn't compile, at least not without IncoherentInstances. Actually, I think now that with one-parameter type classes, if it compiles, it will most likely work, at least I don't see the problems one can create with multi-parameter type classes now.
-Andy