
2008/4/28 Fraser Wilson
what I am trying to say is "if a is an instance of Num, then can be an instance of ValueClass too, and here's how".
Oh, didn't answer this one. This is almost canned response, questions like this get asked weekly on this list. Short answer: you can't. Longer answer: you can, but you have to wrap it in a newtype, which is irritating. newtype NumValue a = NumV a instance (Num a) => ValueClass (NumV a) where fromValue (Value n) = NumV (fromInteger n) Essentially you have to "tell the compiler" when you use this instance. So you still get all the power, but with less convenience (than the impossible thing you want). Abridged longest answer: you can, and you don't need a newtype, but only if you're The Devil. Here's an explanation, but *please do not do this*! It's unpredictable, poor style, a bad habit, nonmodular, etc. etc. etc. First enable undecidable instances: {-# LANGUAGE UndecidableInstances #-} With this pragma you are forfeiting your right to a terminating compiler. The compiler may "instance stack overflow" or run forever for no discernible reason. Now you are allowed exactly one instance of the form you desire: instance (Num a) => ValueClass a where fromValue (Value n) = fromInteger n If you're lucky, you might be able to define some well-formed instances in addition and have everything behave. It *will* break if you add another such instance, for example: instance (Read a) => ValueClass a where ... Because when the compiler sees fromValue, it will try to match it against the head of an instance. Both the Num and the Read forms match every type, so it will *pick one arbitrarily*, without backtracking. So if you wanted the Read one and it picked the Num one, you are permanently out of luck and you basically have to scrap everything. So, yeah, there's a little excursion into the dirty corners of the typeclass system. If you don't want to get spontaneously eaten by a bear, use a newtype as above :-). And now it's time to go make/edit a wiki page on the subject. Luke