News for hackers. Stuff that matters.
Re:Show HN: Code Words, a quarterly publication about progra... by akanet on Saturday December 06, 2014 @12:33AM (#8708472)
Dan Luu's article about transitive equality and floating point numbers is pretty amusing. (https://codewords.hackerschool.com/issues/one/when-is-equali...).

Here's a little tidbit from the article (notice that he's shown an example in Haskell where A == B, B == C, but A != C):

  $ ghci
  Prelude> -- Hi! I'm a comment!
  Prelude> -- 2^53 == 2.0^53
  Prelude>  9007199254740992 == 9007199254740992.0
  True
  Prelude> -- 2.0^53 == 2^53 + 1
  Prelude>  9007199254740992.0 == 9007199254740993
  True
  Prelude> -- 2^53 == 2^53 + 1
  Prelude>  9007199254740992 == 9007199254740993
  False
Re:Show HN: Code Words, a quarterly publication about progra... by copascetic on Saturday December 06, 2014 @12:50AM (#8708493)
This example is misleading, and I don't think the article addresses the subtleties.

Basically, the third line is not like the other two. Because none of the numbers involved in #3 are Doubles, Haskell will actually use the Integer type, which is basically a bignum (like integers in Python).

The first two are comparing values of type Double, so the instance of Eq for Double is used, which necessarily has some inaccuracies, as shown in the second line, while the last one is using the instance of Eq for Integer. Therefore, the statement that (==) is not transitive for these types is false, because we are talking about different versions of (==) in the first two examples vs. the last one.

The trick is that bare numeric literals have type Num a => a, and have their type inferred by their use. The first two examples cause the 2^53 to take on type Double, otherwise it wouldn't type check (literals with decimals in them have type Fractional a => a, of which Double is the default). The last one doesn't have any expressions with decimals, so it uses the Integer type.

Re:Show HN: Code Words, a quarterly publication about progra... by copascetic on Saturday December 06, 2014 @01:09AM (#8708542)
When you specify the types of the numbers used, so that you are testing the transitivity of a single instance of Eq, you will find that transitivity does hold in this case.

  a :: Double
  a = 2^53

  b :: Double
  b = 2.0^53

  c :: Double
  c = 2^53 + 1

  main :: IO ()
  main = do
    print $ a == b -- True
    print $ b == c -- True
    print $ a == c -- True