Unit 3: Floating-point numbers

Introduction

Haskell has two types for floating-point numbers, namely Float (single-precision) and Double (double-precision). Floating-point numbers can be represented in two ways. First, using a decimal point:

2.0
33.873
-8.3377

Second, by means of the so-called scientific notation:

33.61e6
3.7e-2
-3.7e2

These are equivalent to the following, in order:

33.61*106
3.7*10-2
-3.7*102

Haskell has the usual binary infix floating-point operators, namely + (addition), - (subtraction), * (multiplication), / (division) and ** (exponentiation). It has the unary prefix operator - (minus or negative) and the constant pi is also defined. There are several useful unary prefix operators available:

cos cosine
sin sine
tan tangent
log natural logarithm
acos inverse cosine
asin inverse sine
atan inverse tangent
exp power of e
sqrt positive square root

Haskell has some useful functions for converting floating-point numbers into limited-precision integers, namely ceiling 2.3 which is equivalent to 3, floor 2.3 which is equivalent to 2 and round 2.3 which is equivalent to 2. Note that round 2.7 is equivalent to 3. These are all of type Float -> Int.

The function fromInt of type Int -> Float converts a limited-precision integer into a single-precision floating-point number.

Numerical type classes

So far four numerical types in Haskell have been introduced, namely Int, Integer, Float and Double. It is tedious to define a new function that squares its argument, say, for each numerical type:

sqInt :: Int -> Int
sqInt x = x * x

sqInteger :: Integer -> Integer
sqInteger x = x * x

sqFloat :: Float -> Float
sqFloat x = x * x

sqDouble :: Double -> Double
sqDouble x = x * x

Haskell has several type classes which allow one definition to do the work of more than one of the above monomorphic definitions:

sqIntegral :: Integral a => a -> a
sqIntegral x = x * x

sqFractional :: Fractional a => a -> a
sqFractional x = x * x

sqReal :: Real a => a -> a
sqReal x = x * x

The type class Integral contains the types Int and Integer. The type class Fractional contains the types Float and Double. The type class Real contains the types Int, Integer, Float and Double. These, and some other important type classes are shown in Fig. 1, but note that Haskell has many more type classes.

Partial type-class inclusion diagram
Figure 1. Partial type-class inclusion diagram.

Characters

The type Char contains characters. Elements of Char are written enclosed in single closing quotation marks, for example: 'a', 'B', '4', '\t' (tab), '\n' (newline), '\\' (backslash), '\'' (single closing quotation mark) and '\"' (double quotation mark). The single opening quotation mark is simply written between single closing quotation marks, thus '`'.

There are several useful functions defined on characters. The functions toUpper and toLower, both of type Char -> Char, do what you would expect. The function ord, of type Char -> Int, turns a character into its ASCII code. The function chr, of type Int -> Char, turns an ASCII code into a character.

There are also several Boolean-valued functions defined on characters, that is to say, functions of type Char -> Bool. Some of these are: isAscii, isUpper, isLower, isAlpha, isDigit and isAlphaNum.

© Antoni Diller (30 May 2016)