# Show, Eq not necessary for Num [Was: Revamping the numeric classes]

William Lee Irwin III wli@holomorphy.com
Sun, 11 Feb 2001 05:07:21 -0800

On 11-Feb-2001, Brian Boutel <brian@boutel.co.nz> wrote:
>> There may be some misunderstanding here. If you are talking about type
>> for which equality is always undefined, then I agree with you, but that
>> is not what I was talking about. I was thinking about types where
>> equality is defined for some pairs of argument values and undefined for
>> others - I think the original example was some kind of arbitrary
>> precision reals.

On Sun, Feb 11, 2001 at 06:24:33PM +1100, Fergus Henderson wrote:
> The original example was treating functions as a numeric type.  In the
> case of functions, computing equality is almost always infeasible.
> But you can easily define addition etc. pointwise:
>
> 	f + g = (\ x -> f x + g x)

I have a fairly complete implementation of this with dummy instances of
Eq and Show for those who want to see the consequences of this. I found,
interestingly enough, that any type constructor f with the following
three properties could have an instance of Num defined upon f a:

(1) it has a unary constructor to lift scalars
(2) it has a Functor instance
(3) it has an analogue of zip which can be defined upon it

or, more precisely:

\begin{code}
instance (Eq (f a), Show (f a), Num a, Functor f,
Zippable f, HasUnaryCon f) => Num (f a)
where
f + g = fmap (uncurry (+)) $fzip f g f * g = fmap (uncurry (*))$ fzip f g
f - g = fmap (uncurry (-)) $fzip f g negate = fmap negate abs = fmap abs signum = fmap signum fromInteger = unaryCon . fromInteger class Zippable f where fzip :: f a -> f b -> f (a,b) class HasUnaryCon f where unaryCon :: a -> f a instance Functor ((->) a) where fmap = (.) instance Zippable ((->) a) where fzip f g = \x -> (f x, g x) instance HasUnaryCon ((->) a) where unaryCon = const \end{code} and this generalizes nicely to other data types: \begin{code} instance Zippable Maybe where fzip (Just x) (Just y) = Just (x,y) fzip _ Nothing = Nothing fzip Nothing _ = Nothing instance HasUnaryCon Maybe where unaryCon = Just instance Zippable [ ] where fzip = zip instance HasUnaryCon [ ] where unaryCon = cycle . (:[]) \end{code} On 11-Feb-2001, Brian Boutel <brian@boutel.co.nz> wrote: >> Returning to the basic issue, I understood the desire to remove Eq as a >> superclass of Num was so that people were not required to implement >> equality if they did not need it, not that there were significant >> numbers of useful numeric types for which equality was not meaningful. On Sun, Feb 11, 2001 at 06:24:33PM +1100, Fergus Henderson wrote: > The argument is the latter, with functions as the canonical example. Well, usually equality as a mathematical concept is meaningful, but either not effectively or efficiently computable. Given an enumerable and bounded domain, equality may be defined (perhaps inefficiently) on functions by \begin{code} instance (Enum a, Bounded a, Eq b) => Eq (a->b) where f == g = all (uncurry (==))$ zipWith (\x -> (f x, g x)) [minBound..maxBound]
\end{code}

and as I've said in another post, equality instances on data structures
expected to be infinite, very large, or where the semantics of equality
are make it difficult to compute, or perhaps even cases where it's just
not useful are also not good to be forced.

Cheers,
Bill