A sample revised prelude for numeric classes

Dylan Thurston [email protected]
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

> > > 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.

	Dylan Thurston