On Dec 5, 2009, at 6:58 PM, Michael Snoyman wrote: > Hi all, > > Well, I've got two problems which both want to be solved with undecidable and > overlapping instances. Obviously, I'd like to try and avoid them. For the > record, the problems have to do with the control-monad-failure and > convertible packages. The code below *should* make clear what I'm trying to > accomplish: > > -- failure should not be limited to just monads, so... > class Failure e f where > failure :: e -> f v > class (Functor f, Failure e f) => FunctorFailure e f > instance (Functor f, Failure e f) => FunctorFailure e f -- undecidable, > overlaps > class (Applicative f, Failure e f) => ApplicativeFailure e f > instance (Applicative f, Failure e f) => ApplicativeFailure e f -- > undecidable, overlaps > class (Monad f, Failure e f) => MonadFailure e f > instance (Monad f, Failure e f) => MonadFailure e f -- undecidable, overlaps >
(Functor|Monad|Applicative)Failure are little more than class synonyms, right ? Or equivalently, do you envision the need of writing, say, a MonadFailure instance for a type A which which works differently than the existing Failure instance for A? If the answer is no as I presume, then you don't want overlapping instances. Regarding undecidable instances, I will say that from my point of view they do not constitute a language extension. MPTCs are the language extension here. Since MPTCs can lead to non-terminating type checking, a compiler can either allow any use of them, employ a termination prover to ensure that only well-behaved instances are defined, or impose a set of restrictions that ensure termination. GHC does the latter, rather conservatively in some cases, and undecidable instances is just a compiler flag that puts the burden of termination checking on the user. In this case it is obvious that non-termination is not going to be a problem for the instances defined above. Since you have already decided MPTCs are ok, in my opinion undecidable instances are fine here. But I realize this is not the usual stance, so I might be wrong. > And now the convertible issue. I want two type classes: Convert for anything > which *might* be convertible, but might not. For example, sometimes a String > can be converted to an Int (like the string "5"), but sometimes it will fail > (like "five"). TotalConvert is when something *is* convertible, such as Int > to String (simply the show function). Thus the following: > > class Convert x y where > convert :: x -> Maybe y > class Convert x y => TotalConvert x y where > totalConvert :: x -> y > instance TotalConvert x y => Convert x y where -- Boom! > convert = Just . totalConvert In this case Convert is not just a class synonym, so you are going to run into trouble with that code. I would do this as follows: class Convert x y => TotalConvert x y where totalConvert :: x -> y totalConvert = fromJust . convert For instance, instance Convert Integer Double where convert = Just . fromIntegral instance TotalConvert Double -- that's all Cheers, pepe_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe