roundable: Split out the Roundable class.
[altfloat.git] / Data / Roundable.hs
blob041ac9cbce202059414d0435f42ad6a5037d408d
1 {-
2 - Copyright (C) 2009-2010 Nick Bowler.
4 - License BSD2: 2-clause BSD license. See LICENSE for full terms.
5 - This is free software: you are free to change and redistribute it.
6 - There is NO WARRANTY, to the extent permitted by law.
7 -}
9 -- | A replacement for the 'RealFrac' class which is usable by floating point
10 -- types. The functions in 'RealFrac' shoehorn their results into an integer,
11 -- which means they simply cannot be defined sensibly for infinities or NaNs.
12 module Data.Roundable where
14 import Prelude hiding (Ord(..), ceiling, floor, truncate, round)
15 import Data.Ratio
16 import Data.Poset
18 -- | Class for ordered numeric types which embed a subset of the integers.
20 -- Minimal complete definition: 'toIntegral' and 'round'.
21 class (Fractional a, Poset a) => Roundable a where
22 -- | Discards the fractional component from a value. Results in 'Nothing'
23 -- if the result cannot be represented as an integer, such as if the input
24 -- is infinite or NaN.
25 toIntegral :: Integral b => a -> Maybe b
26 -- | Determine the least integer not less than the input.
27 ceiling :: a -> a
28 -- | Determine the greatest integer not greater than the input.
29 floor :: a -> a
30 -- | Determine the greatest integer whose absolute value is not greater
31 -- than the input.
32 truncate :: a -> a
33 -- | Determine the integer closest to the input. In case of a tie, the
34 -- integer largest in absolute value is chosen.
35 round :: a -> a
37 floor x
38 | round x == x = x
39 | otherwise = round $ x - fromRational (1%2)
40 ceiling x
41 | round x == x = x
42 | otherwise = round $ x + fromRational (1%2)
43 truncate x
44 | x < 0 = ceiling x
45 | x > 0 = floor x
46 | otherwise = x
48 instance Integral a => Roundable (Ratio a) where
49 toIntegral = Just . fst . properFraction
50 round x
51 | abs frac >= 1%2 = int%1 + signum frac
52 | otherwise = int%1
53 where (int, frac) = properFraction x