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
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe