What's the difference between the classes Floating and Fractional in Haskell?
Asked Answered
L

2

20

What is the difference is between the Floating and Fractional classes in Haskell?

Limpid answered 31/1, 2017 at 17:50 Comment(6)
They're right next to each other in the Prelude.Symposiac
What do you want to say exactly?Limpid
Is there really no info on the docs?Larochelle
No more information is needed for this question.Limpid
Docs are indeed very poorGosh
Potential close voters: this question is definitely not unclear.Biting
H
9

The definitions of Fractional and Floating can be found in the documentation of the Prelude:

class Num a => Fractional a where
    (/) :: a -> a -> a
    recip :: a -> a
    fromRational :: Rational -> a 

Fractional numbers, supporting real division.

[...]

class Fractional a => Floating a where
    pi :: a
    exp :: a -> a
    log :: a -> a
    sqrt :: a -> a
    (**) :: a -> a -> a
    logBase :: a -> a -> a
    sin :: a -> a
    cos :: a -> a
    tan :: a -> a
    asin :: a -> a
    acos :: a -> a
    atan :: a -> a
    sinh :: a -> a
    cosh :: a -> a
    tanh :: a -> a
    asinh :: a -> a
    acosh :: a -> a
    atanh :: a -> a

Trigonometric and hyperbolic functions and related functions.

[...]

So to translate that into English: A Fractional is any kind of number for which I can define a division:

(/) :: Fractional a => a -> a -> a

That can for instance be the case for floating point numbers, but also for fractions (where a fraction has a numerator and denominator). This is not the case for Int because if dividing an Int by an Int does not always produce an Int (well technically floating point division on a computer is not exact, but that is another story).

A subset of Fractional numbers are Floating numbers where trigonometric are defined. It is for instance impossible that the sin of a fraction always produces a fraction: a sin is defined as an sum over an infinite sequence. Only for a very limited number of cases (like sin 0) it holds. Basically the only numbers on a computer for which trigonometric are defined (approximatively) are floating point numbers.

Holyhead answered 31/1, 2017 at 18:3 Comment(0)
W
12

Very roughly:

  • Fractional is the class of types that can represent (exactly or at least in a decent approximation) any rational number. It may ad lib also be able to represent other numbers, but that's not important.
    In other terms, it's just the class of number types that have a division operation; since it's a subclass of Num it follows from this that the types must contain the rational numbers.

  • Floating is the class of number types that are closed under limits in the Cauchy sense, i.e. complete spaces. This is necessary to do any sort of calculus. The methods of the Floating class are functions that are mathematically defined as limits, namely infinite sums (which are the limits of the sequence of partial sums of taylor series).
    Since you can define the real numbers as limits of sequences of rational numbers and because again Floating is a subclass of Fractional, any Floating type is able to represent (again, at least to a decent approximation) any real number.

A good way to visualise the difference is through topology: Floating types are connected spaces, i.e. they form a continuum. What this means for floating point numbers is: every value is understood as a whole interval of real numbers (because floating-point always has some uncertainty). When you lay these intervals side by side, you tile the entire real numbers (at least to ±10300) without gaps.

By contrast, some Fractional types are not connected. In particular, Rational can exactly represent all its (rational-number) values, so each value is just an “infinitely small point”. You can never cover the entire real line with such points, and you can not compute functions like sin or log since the result of these functions is usually a non-rational real number.


It's worth pondering a bit what this “decent approximation” means. The Haskell standard doesn't define this. This story about every floating point number representing a whole interval of real numbers captures it quite well IMO. More generally, we might say: Num/Fractional/Floating are the classes of types that represent equivalance classes of integer/rational/real numbers. In fact, these classes need not even be “small” intervals: in particular the finite types like Word32 or the standard Int can be understood in a modular arithmetic sense, manifesting in results like (2^70 :: Int) == 0, i.e. the equivalence classes are then numbers spaces by a multiple of 264.

In cases like Integer or Rational, the equivalence classes actually contain only a single element, i.e. the numbers are represented exactly. For real numbers, this is actually also possible, but much more tricky, it's called exact real arithmetic. There are libraries such as aern that do this.

Whyalla answered 31/1, 2017 at 18:14 Comment(5)
Isn't it a bit misleading to say "Fractional types are not connected" since the set of Floating types is a subset of Fractional types (since class Fractional a => Floating a)? It's like saying "things that carry DNA/RNA are living" and forgetting about viruses (that have RNA but no metabolism).Holyhead
@WillemVanOnsem If a fractional type is floating, then it's connected, but if it's not connected, then it's not floating.Symposiac
@JoshLee: Yeah, I know that: but I think the answer can be a bit confusing to that point...Holyhead
@WillemVanOnsem I said some Fractional types are not connected, and gave Rational as an example.Whyalla
@leftaroundabout: Yeah for some reason the first time I looked I did not spotted the some :( Probably bit overworked because of the Berlinade deadline :)Holyhead
H
9

The definitions of Fractional and Floating can be found in the documentation of the Prelude:

class Num a => Fractional a where
    (/) :: a -> a -> a
    recip :: a -> a
    fromRational :: Rational -> a 

Fractional numbers, supporting real division.

[...]

class Fractional a => Floating a where
    pi :: a
    exp :: a -> a
    log :: a -> a
    sqrt :: a -> a
    (**) :: a -> a -> a
    logBase :: a -> a -> a
    sin :: a -> a
    cos :: a -> a
    tan :: a -> a
    asin :: a -> a
    acos :: a -> a
    atan :: a -> a
    sinh :: a -> a
    cosh :: a -> a
    tanh :: a -> a
    asinh :: a -> a
    acosh :: a -> a
    atanh :: a -> a

Trigonometric and hyperbolic functions and related functions.

[...]

So to translate that into English: A Fractional is any kind of number for which I can define a division:

(/) :: Fractional a => a -> a -> a

That can for instance be the case for floating point numbers, but also for fractions (where a fraction has a numerator and denominator). This is not the case for Int because if dividing an Int by an Int does not always produce an Int (well technically floating point division on a computer is not exact, but that is another story).

A subset of Fractional numbers are Floating numbers where trigonometric are defined. It is for instance impossible that the sin of a fraction always produces a fraction: a sin is defined as an sum over an infinite sequence. Only for a very limited number of cases (like sin 0) it holds. Basically the only numbers on a computer for which trigonometric are defined (approximatively) are floating point numbers.

Holyhead answered 31/1, 2017 at 18:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.