Closed non closed 9 years ago
This would resolve (or at least works towards resolving) #10.
Also, I'd love for @tixxit and @larsrh to review this. I based this all on Spire's laws but I did some updating. In particular I created functions in Rules.scala that allow me to avoid duplicating definitions for things like associativity, commutativity, distributivity, and so on.
I think it's pretty elegant but it does add some indirection. What do you all think?
Also, @johnynek and @avibryant, do these ScalaCheck/Discipline tests make sense to you all? It's pretty expressive and allows "inheriting" properties, but there is definitely a bit of a learning curve.
Oh also, one additional comment:
In Spire we use Eq[A]
(and the associated infix operators ===
and =!=
) for all equality checks.
Since this project consciously avoids adding infix operators, to keep the tests readable I converted all these checks to ==
and !=
:cry:. However, the tests still require an Eq[A]
instance so that in the future we can convert back if we want (and also to ensure that we believe equality is sensible for the given type).
Yep, the laws absolutely make sense.
From the last commit:
This commit does a few things:
1. Restores clobbered project/build.scala file.
2. Add ?-prefixed ScalaCheck operators for better test output
3. Improves the laws a bit
4. Adds many std instances, and checks the laws against them
5. Implements toy rational type ("Rat"); tests the field laws.
At this point I feel like the laws are in good enough shape for
others to start building on. We can also add more std instances.
For now, I am trying to keep the std instances as simple as
possible. This means no specialization, and also no performance
concerns. I don't think we should plan to port over "real" types
to std, but rather use it to check laws and provide simple code.
So, after realizing we weren't testing the IsReal[A]
methods with any laws, I added some laws and of course immediately found a bug in Rat
. That'll teach me not to write laws.
At this point all the type classes have laws except NRoot[A]
. I will add some laws now, until we add a type like spire.math.Algebraic
or spire.math.Real
I fear we won't have any types that can actually pass all the tests (e.g. x.pow(3).nroot(3) = x.nroot(3).pow(3) = x
).
I sort of went crazy and started implementing a symbolic type to allow law-checking of things like x.nroot(k).pow(k) = x.pow(k).nroot(k) = x
. Ultimately this seemed like a bad thing to ship in algebra.std
so I spun it out to its own project.
I just pushed some commits which (I think) should address all the issues we've seen so far.
Please let me know if there's anything else you think is needed.
(Also, I think I need to update this PR now that lattices are merged. I'll do that right now.)
Alright, so the last four commits update this PR to be lattice-aware.
It also adds the three files of laws relating to lattices (LatticeLaws.scala
, LogicLaws.scala
, and LatticePartialOrderLaws.scala
).
So I went ahead and removed the dependencies from algebra-std
as I proposed earlier. Let me know what you all think.
Most recent commits merge the support for commutativity to this branch, and update the laws accordingly.
The nice thing is that the previous PR couldn't have tests -- but in this branch we were able to confirm that all the instances we had defined were in fact commutative! :fireworks:
:+1:
What do you think @johnynek? Anything else you'd like to see done on this PR?
This commit creates three sub-projects:
It also ports over the basic laws from Spire for:
Finally, it adds a very simple standard algebra instance for Int, and runs the relevant laws tests on it.