Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export the Rational type constructor #3

Open
wants to merge 19 commits into
base: master
Choose a base branch
from

Conversation

newlandsvalley
Copy link

The constructor is renamed from Ratio to Rational and exported.
(also add .gitignore)

The constructor is renamed from Ration  to Rational and exported.
(also add .gitignore)
1) Normalised 'over' when faced with negative denominators
2) Added various (mostly logical) combinators
3) Added some QuickCheck-style tests
4) Reverted to hiding the constructor to enable normalisation
@imeckler
Copy link
Owner

With regard to exposing the constructor, I've responded to your comment in the issue.

I appreciate the comparison functions. I think I would prefer they be implemented in terms of a single function

compare : Rational -> Rational -> Order
compare (Ratio a b) (Ratio c d) = Basics.compare (a * d) (c * b)

And I'm not sure if they should be named gt or > for example. Is there an established convention yet in Elm for this sort of thing?

@newlandsvalley
Copy link
Author

Good idea - this is a much better implementation than the one I attempted. We're obviously hampered by the lack of type classes in elm. Ideally it would be good just to overload the arithmetic and comparison operators and have Rational belong to comparable and number but that's never going to happen, I suspect.

I attempted to use > instead of gt but then I couldn't get it to compile. I think it was because there was confusion over the operator from both Basics and Rational and it didn't seem to like my disambiguating the implementation by saying Basics.(>).

What's also a pain is mixed-type arithmetic. I need to multiply and divide Rationals with Integers all over the place in my current project and converting every Int to a Rational in a long arithmetic expression is just plain tedious. However I can't think of a good elmish idiomatic way to express these operations.

Also added more tests to investigate the behaviour of Rationals representing Infinity (Rational 1 0)
The idea is that the conventional comparison and arithmetic operands are used but whenever a Rational is at a given side of the operator, then the operator is 'protected' by a '|' character.  This both avoids clashes with Basics operators and also gives a method of predicting what the operator is with either one or two Rationals in a given context.
@newlandsvalley
Copy link
Author

I have a proposal:

  1. We retain the 'wordy' version of each comparison and arithmetic operator.
  2. We provide, as an option for users, a separate module Ratio.Infix with infix versions of as many operators as makes sense to use.
  3. We adopt the convention that we use the normal symbol for the operator, but we add to it two vertical bar lines if both operands are Rationals; one vertical bar if one operand is a Rational but the other is an Int - as fleshed out here. For example:
(|>|) : Rational -> Rational -> Order 

(|*|) : Rational -> Rational -> Rational

(|*) : Rational -> Int -> Rational

(*|) : Int -> Rational -> Rational

This has the advantage that a) a user doesn't need to import or use the infix version and b) if she does use it, then there are no clashes with the equivalent operators in Basics. (Writing Ratio.(>) everywhere would be counter-productive.)

There is some precedent for this - for example see Bogdan Popa's elm-combine infix operators.

@imeckler
Copy link
Owner

(1) and (2) sound good to me. I particularly like the idea of having a separate infix module, though I'm not crazy about these operator names. I think it's more complexity than is generally useful, and I'd prefer to just stick with

(>) : Rational -> Rational -> Bool
... other infix comparison functions ...
(*) : Rational -> Rational -> Rational
(+) : Rational -> Rational -> Rational
(/) : Rational -> Rational -> Rational

@newlandsvalley
Copy link
Author

newlandsvalley commented Aug 18, 2016

Suppose the user has a simple expression where r1 and r2 are Rationals;

result = (20 + 30 + r1) / (70 * r2)

and envisage what the expression would look like using the two schemes outlined above for infix names. I know that the infix symbols I propose are ugly and generally disliked but they have the advantage of being both terse and free of ambiguity. If we don't use something like this, every operator will have to be qualified by its module name. I feel this is very important, but I'm open to other suggestions .....

I think I will continue to experiment with these ideas in my fork. Feel free to cancel this pull request because I know you're not keen.

Also a naive implementation of the expected Expect.almostEqual function for comparing Floats in QuickCheck style tests.
This is a rough prototype of a possible future function for testing near-quality in numbers (particularly floats).
(This project now moved to elm-community)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants