Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions posts/2019-12-14-stern-brocot.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ In Haskell, that kind of means doing the following:

```haskell
instance Eq Frac where
(x :/ xd) == (y :/ yd) = (x * yd) == (y * xd)
(x :/ xd) == (y :/ yd) = (x * toInteger yd) == (y * toInteger xd)

instance Ord Frac where
compare (x :/ xd) (y :/ yd) = compare (x * yd) (y * xd)
compare (x :/ xd) (y :/ yd) = compare (x * toInteger yd) (y * toInteger xd)
```

We don't have real quotient types in Haskell, but this gets the idea across: we
Expand All @@ -110,10 +110,10 @@ Th `Num` instance is pretty much just a restating of the axioms for fractions.
instance Num Frac where
fromInteger n = fromInteger n :/ 1
(x :/ xd) * (y :/ yd) = (x * y) :/ (xd * yd)
(x :/ xd) + (y :/ yd) = (x * yd + y * xd) :/ (xd * yd)
signum = (:/ 1) . signum . numerator
abs = id
(x :/ xd) - (y :/ yd) = (x * yd - y * xd) :/ (xd * yd)
(x :/ xd) + (y :/ yd) = (x * toInteger yd + y * toInteger xd) :/ (xd * yd)
signum (x :/ _) = signum x :/ 1
abs (x :/ xd) = abs x :/ xd
(x :/ xd) - (y :/ yd) = (x * toInteger yd - y * toInteger xd) :/ (xd * yd)
```
</details>

Expand Down Expand Up @@ -184,10 +184,10 @@ type Rational = [Bit]
abs :: Frac -> Rational
abs = unfoldr f
where
f (n :/ d) = case compare n d of
f (n :/ d) = case compare n (toInteger d) of
EQ -> Nothing
LT -> Just (O, n :/ (d - n))
GT -> Just (I, (n - d) :/ d)
LT -> Just (O, n :/ (d - fromInteger n))
GT -> Just (I, (n - toInteger d) :/ d)
```

And since we used `unfoldr`, it's easy to reverse the algorithm to convert from
Expand All @@ -197,8 +197,8 @@ the representation to a pair of numbers.
rep :: Rational -> Frac
rep = foldr f (1 :/ 1)
where
f I (n :/ d) = (n + d) :/ d
f O (n :/ d) = n :/ (n + d)
f I (n :/ d) = (n + toInteger d) :/ d
f O (n :/ d) = n :/ (fromInteger n + d)
```

Now `abs . rep` is the identity function, and `rep . abs` reduces a fraction!
Expand Down