Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unclear why functions from Data.Ratio are not exposed and how to work around

I am implementing an algorithm using Data.Ratio (convergents of continued fractions). However, I encounter two obstacles:

  • The algorithm starts with the fraction 1%0 - but this throws a zero denominator exception.
  • I would like to pattern match the constructor a :% b

I was exploring on hackage. An in particular the source seems to be using exactly these features (e.g. defining infinity = 1 :% 0, or pattern matching for numerator).

As beginner, I am also confused where it is determined that (%), numerator and such are exposed to me, but not infinity and (:%).

I have already made a dirty workaround using a tuple of integers, but it seems silly to reinvent the wheel about something so trivial. Also would be nice to learn how read the source which functions are exposed.

like image 207
bdecaf Avatar asked Aug 07 '20 07:08

bdecaf


1 Answers

They aren't exported precisely to prevent people from doing stuff like this. See, the type

data Ratio a = a:%a

contains too many values. In particular, e.g. 2/6 and 3/9 are actually the same number in ℚ and both represented by 1:%3. Thus, 2:%6 is in fact an illegal value, and so is, sure enough, 1:%0. Or it might be legal but all functions know how to treat them so 2:%6 is for all observable means equal to 1:%3 – I don't in fact know which of these options GHC chooses, but at any rate it's an implementation detail and could change in future releases without notice.

If the library authors themselves use such values for e.g. optimisation tricks that's one thing – they have after all full control over any algorithmic details and any undefined behaviour that could arise. But if users got to construct such values, it would result in brittle code.

So – if you find yourself starting an algorithm with 1/0, then you should indeed not use Ratio at all there but simply store numerator and denominator in a plain tuple, which has no such issues, and only make the final result a Ratio with %.

like image 161
leftaroundabout Avatar answered Sep 29 '22 06:09

leftaroundabout