Search code examples
haskellrational-number

Why do I get this result when adding two rational numbers in Haskell


Consider this short GHCi session:

ghci> import Data.Ratio
ghci> import Data.Word
ghci> 128 % 3 + 127 % 3 :: Ratio Word8
253 % 9

Why is the result 253 % 9 and not 255 % 3 (= 85 % 1)?

That, really, is my question, but I'll be happy to elaborate.


First, if I remove the type, the result is what I'd expect:

ghci> 128 % 3 + 127 % 3
85 % 1

The type Word8 seems important. I'm aware of potential integer overflow, but even so, I can't make sense of the result. E.g.

ghci> 128 + 127 :: Word8
255

There's no overflow here. That first happens at

ghci> 128 + 128 :: Word8
0
ghci> 128 + 129 :: Word8
1

If I divide by two instead of three, I can still comprehend the results:

ghci> 128 % 2 + 127 % 2 :: Ratio Word8
255 % 2
ghci> 128 % 2 + 128 % 2 :: Ratio Word8
128 % 1
ghci> 128 % 2 + 129 % 2 :: Ratio Word8
1 % 2
ghci> 129 % 2 + 129 % 2 :: Ratio Word8
1 % 1

Here 128 % 2 + 128 % 2 even produces 128 % 1 as one would hope. All of this seems to make perfect sense as 'normal' modulo-256 arithmetic, but then what happens when I work in thirds instead of halves? Why is the denominator 9?


Solution

  • It's because addition for the rationals is defined as

    (x:%y) + (x':%y')   =  reduce (x*y' + x'*y) (y*y')
    

    Since everything here is Word8, each individual operation is performed mod 256.

    (128*3)   `mod` 256 = 128
    (127*3)   `mod` 256 = 125
    (128+125) `mod` 256 = 253