Version 12 (modified by ross@…, 10 years ago) (diff)

add note on Enum ⇒ Integral from #112

Issues with Standard Classes

This page collects issues and proposals for the standard classes. Many of the proposals involve additional superclasses, which would be less burdensome with class aliases or something similar, but such features are not yet implemented.


Constructor classes

The Functor class


  • Add instances for ((->) a), ((,) a) and Either a.

The Monad class


  • Monads are really functors, but programmers can't always assume that fmap is defined for them, and so must use liftM instead. Similarly, code parameterized by Functor cannot be used with monads.
  • The fail method was added to the class in Haskell 98 to implement pattern match failure in do expressions. However the assumption that errors are strings can be problematic (e.g. cf the Error class in Control.Monad.Error, or for internationalization).


  • Add instance for ((->) a).
  • Make Functor a superclass of Monad. This would impose an extra burden on those who just want to define a Monad.
  • Make join a method of Monad, interdefined with (>>=).
  • A more extreme step down this road would be to interpose the new Applicative class between Functor and Monad, with corresponding renaming of methods.


The Haskell 98 numeric classes are adequate for Haskell 98 numeric types, but other mathematical objects do not fit. If the Haskell 98 classes were retained for backwards compatibility, but with a more refined class hierarchy, the change would impact mostly on those defining instances (and these are the people inconvenienced by the current system). Clients of the classes would notice only some more general types.

The Num class


  • Eq and Show don't make sense for functions under lifting.
  • (*) doesn't make sense for vectors.
  • abs and signum don't make sense for Complex Integer (Gaussian integers), vectors, matrices, etc. In general, abs and signum make it hard to lift Num through type constructors.


  • A group-like class with zero, (+) and negate/(-).
  • (Could be further split with a monoid sub-class.)
  • A ring-like subclass adding (*) and one/fromInteger, with the existing Num class as a further subclass.
  • (Could be further split with a semiring subclass, e.g. for natural numbers.)

Note that the Float and Double instances will not satisfy the usual axioms for these structures.

The Fractional class


  • (/), recip and fromRational can be lifted to functions, but many of the pre-requisites can't be defined for these.


  • Add a division ring-like superclass adding these operations to the ring-like class. (A division ring has the same operations as a field, but does not assume commutative multiplication, allowing structures such as quaternions.)
  • Add default
    fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
    This is independent of all the other proposals.

The Integral class


  • div and mod also sense for rationals, polynomials and Gaussian integers, but Enum and toInteger do not.
  • Ord, Num(abs, signum) and toRational don't make sense for polynomials and Gaussian integers.
  • quot and rem assume an ordering.

Other standard classes

The Read class

See ReadClass.

The Enum class


  • succ and pred are unused.
  • The default definitions of enum* would make more sense if toEnum and fromEnum used Integer instead of Int.
  • Some doubt that it makes sense to have Float and Double instances.
  • It is wierd that [0,3..20]::[Rational] includes 21.

The Ix class


  • There is no portable way to report indexing errors accurately.


  • Make Show a superclass of Ix, so that the offending index and range can be shown in exceptions. (All instances of Ix in the base package are also instances of Show.)

The Bits class


  • The Num superclass may unduly restrict instances. The only thing actually needed from Num is 0.
  • The bitSize method is not defined for all instances, and there is no general way to test whether it can be safely called.

The Storable class


  • Some interfaces require clients to manage the memory for objects, but to treat them abstractly. In such cases one wants to define sizeOf and alignment (to use malloc or alloca), but not peek or poke.