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

Reply via email to