A sample revised prelude for numeric classes
Dylan Thurston
dpt@math.harvard.edu
Sun, 11 Feb 2001 22:27:53 -0500
Thanks for the comments!
On Mon, Feb 12, 2001 at 12:26:35AM +0000, Marcin 'Qrczak' Kowalczyk wrote:
> I don't like the fact that there is no Powerful Integer Integer.
Reading this, it occurred to me that you could explictly declare an
instance of Powerful Integer Integer and have everything else work.
> Then the second argument of (^) is always arbitrary RealIntegral,
Nit: the second argument should be an Integer, not an arbitrary
RealIntegral.
> > > class (Real a, Floating a) => RealFrac a where
> > > -- lifted directly from Haskell 98 Prelude
> > > properFraction :: (Integral b) => a -> (b,a)
> > > truncate, round :: (Integral b) => a -> b
> > > ceiling, floor :: (Integral b) => a -> b
>
> Should be RealIntegral instead of Integral.
Yes. I'd actually like to make it Integer, and let the user compose
with fromInteger herself.
> Perhaps RealIntegral should be called Integral, and your Integral
> should be called somewhat differently.
Perhaps. Do you have suggestions for names? RealIntegral is what
naive users probably want, but Integral is what mathematicians would
use (and call something like an integral domain).
> > > class (Real a, Integral a) => RealIntegral a where
> > > quot, rem :: a -> a -> a
> > > quotRem :: a -> a -> (a,a)
> > >
> > > -- Minimal definition: toInteger
>
> You forgot toInteger.
Oh, right. I actually had it and then deleted it. On the one hand,
it feels very implementation-specific to me, comparable to the
decodeFloat routines (which are useful, but not generally
applicable). On the other hand, I couldn't think of many examples
where I really wouldn't want that operation (other than monadic
numbers, that, say, count the number of operations), and I couldn't
think of a better place to put it.
You'll notice that toRational was similarly missing.
My preferred solution might still be the Convertible class I mentioned
earlier. Recall it was
class Convertible a b where
convert :: a -> b
maybe with another class like
class (Convertible a Integer) => ConvertibleToInteger a where
toInteger :: a -> Integer
toInteger = convert
if the restrictions on instance contexts remain. Convertible a b
should indicate that a can safely be converted to b without losing any
information and maintaining relevant structure; from this point of
view, its use would be strictly limited. (But what's relevant?)
I'm still undecided here.
Best,
Dylan Thurston