A sample revised prelude for numeric classes
Dylan Thurston
dpt@math.harvard.edu
Tue, 13 Feb 2001 14:01:25 -0500
On Mon, Feb 12, 2001 at 12:26:35AM +0000, Marcin 'Qrczak' Kowalczyk wrote:
> I must say I like it. It has a good balance between generality and
> usefulness / convenience.
>
> Modulo a few details, see below.
>
> > > class (Num a, Additive b) => Powerful a b where
> > > (^) :: a -> b -> a
> > > instance (Num a) => Powerful a (Positive Integer) where
> > > a ^ 0 = one
> > > a ^ n = reduceRepeated (*) a n
> > > instance (Fractional a) => Powerful a Integer where
> > > a ^ n | n < 0 = recip (a ^ (negate n))
> > > a ^ n = a ^ (positive n)
>
> I don't like the fact that there is no Powerful Integer Integer.
> Since the definition on negative exponents really depends on the first
> type but can be polymorphic wrt. any Integral exponent, I would make
> other instances instead:
>
> instance RealIntegral b => Powerful Int b
> instance RealIntegral b => Powerful Integer b
> instance (Num a, RealIntegral b) => Powerful (Ratio a) b
> instance Powerful Float Int
> instance Powerful Float Integer
> instance Powerful Float Float
> instance Powerful Double Int
> instance Powerful Double Integer
> instance Powerful Double Double
OK, I'm slow. I finally understand your point here. I might leave
off a few cases, and simplify this to
instance Powerful Int Int
instance Powerful Integer Integer
instance (Num a, SmallIntegral b) => Powerful (Ratio a) b
instance Powerful Float Float
instance Powerful Double Double
instance Powerful Complex Complex
(where "SmallIntegral" is a class that contains toInteger; "small" in
the sense that it fits inside an Integer.) All of these call one of 3
functions:
postivePow :: (Num a, SmallIntegral b) => a -> b -> a
integerPow :: (Fractional a, SmallIntegral b) => a -> b -> a
analyticPow :: (Floating a) => a -> a -> a
(These 3 functions might be in a separate module from the Prelude.)
Consequences: you cannot, e.g., raise a Double to an Integer power
without an explicit conversion or calling a different function (or
declaring your own instance). Is this acceptable? I think it might
be: after all, you can't multiply a Double by an Integer either...
You then have one instance declaration per type, just as for the other
classes.
Opinions? I'm still not very happy.
Best,
Dylan Thurston