Good idea! Many of the Haskell classes don’t really have PureScript analogues.
Num
I think Haskell’s Num is closest to our Ring. For instance, from the Haskell docs:
The Haskell Report defines no laws for
Num. However, ‘(+)’ and ‘(*)’ are customarily expected to define a ring and have the following properties: […]
and the properties they list are more or less the same as the laws on Ring. The differences are:
- PureScript’s
Ringdefines memberszeroandonefor the identities of addition and multiplication, whereasNumis a bit more general and defines afromIntegermember which subsumes both (sincefromInteger 0is expected to be the additive identity, andfromInteger 1is expected to be the multiplicative identity). - Haskell’s
Numincludesabsandsignum, but PureScript’sRingdoesn’t. Theabsandsignumfunctions are a little bit harder to justify from a mathematical perspective (they aren’t part of the definition of a ring).
The omission of fromInteger doesn’t harm us too much, since conversion from any integer type to a ring can be reconstructed fairly easily with what PureScript’s Ring gives you:
import Data.Monoid (power)
import Data.Monoid.Additive (Additive(..))
fromInt :: forall a. Ring a => Int -> a
fromInt x =
if x >= 0
then runAdditive (power (Additive one) x)
else negate (fromInt (negate x))
Real
I am not sure why this class is called Real. I think a better name would be ToRational, because all it does is define a mapping to Rational. There is no type class for this in PureScript; you’ll have to use monomorphic functions if you want to convert some number type to Rational.
Integral
Integral numbers, supporting integer division. The Haskell Report defines no laws for
Integral. However,Integralinstances are customarily expected to define a Euclidean domain and have the following properties for the ‘div’/‘mod’ and ‘quot’/‘rem’ pairs, given suitable Euclidean functionsfandg: […]
This is based on the same idea as PureScript’s EuclideanRing. Differences:
- Haskell puts two pairs of functions into the class,
div/modandquot/rem. PureScript only puts one pair of functions in,div/mod. Note that some types which have aEuclideanRinginstance admit more than one law-abidingEuclideanRinginstance, and in particularIntandBigIntboth do; see my post Different kinds of integer division for details. If you care about what kind of division you’re using thenIntandBigIntprovide monomorphic versions ofquotandrem, or alternatively you could define a newtype wrapper. - Haskell includes a
toIntegerin this class, which limits its utility a little, since there are quite a few examples of Euclidean rings which can’t sensibly be converted to integers. One example is polynomials with coefficients in a field (such as the rationals).
Fractional
This is basically the same as our DivisionRing:
The Haskell Report defines no laws for
Fractional. However, ‘(+)’ and ‘(*)’ are customarily expected to define a division ring and have the following properties: […]
Unlike PureScript’s DivisionRing, Haskell’s Fractional also provides a fromRational. However, we can reconstruct fromRational fairly easily with what DivisionRing gives us, by converting the numerator and denominator (which will be integers) to our type, and then dividing them with the division given by our type.
Floating
Functions like exp, sin, asin. We don’t really have much need for this class since there is only one floating-point type in PureScript, and that’s Number. If you’re porting a Haskell function which uses a Floating constraint then you probably want to make it monomorphic and use the functions from Math.
RealFrac
Doesn’t exist in PureScript. You’ll probably have to write your own if you need any of these.
RealFloat
Doesn’t exist in PureScript. You’ll probably have to write your own if you need any of these.