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

Implementing IsLawfulNum as part of Issue #108 #331

Merged
merged 18 commits into from
Jul 9, 2024

Conversation

pmbittner
Copy link
Contributor

@pmbittner pmbittner commented Jun 8, 2024

This pull-request adds the laws for the Num typeclass in Haskell as part of issue #108.

Progress:

  • formalized the laws for Num typeclass
  • Nat instance
  • Int instance
  • Integer instance
  • Word instance
  • Double instance

There was one law we cannot formalize yet, which is fromInteger (toInteger i) == i because there is no toInteger function available yet. I documented this law as missing.

For the Nat instance, I mostly copied code from the Agda standard library for comparability, consistency, and also because it is easy 😅.

For Integer I had to come up with new proofs because the definitions for this type are slightly different from those in the standard library. I oriented on the proofs from the standard library where possible though. Also I tried to favor equational reasoning in favor of rewrite for better readability.

Arithmetics of Word is mostly relying on arithmetics of Nat and arithmetics of Int is defined solely in terms of arithmetics on Word. I hence opted to reuse the laws from the other instances, respectively. In fact, reducing the arithmetics for a Num type in terms of another Num instance is feasible as long as this reduction is homomorphic.

To formalize this observation, I added definitions for homomorphisms, embeddings, as well as some other common predicates in a new module Haskell.Prim.Function with respective proofs in Haskell.Law.Function. I thought that such definitions might be useful in other contexts as well, if desired. Using these definitions, we can then define the circumstances under which we may conclude an ILawfulNum instance from another one.

The question remains whether such abstractions are desired. On the one hand, these are quite common concepts. On the other hand, they introduce another layer of indirection and abstractions, making some of the proofs harder to comprehend. Also, should we reuse the definitions such as Associative, Commutative, and so on in the definition of IsLawfulNum or should we inline those (as it currently is) for readability?

Moreover, I had to introduce six new axioms to prove lawfulness of Word, all of which are stated in lib/Haskell/Law/Num/Word.agda. I documented the new axioms and explained why they should be reasonable. It would be good if these could be reviewed. I am not 100% sure that they are correct and minimal.

Also, the Double instance cannot be proven as of now. It is solely based on primitive functions for which no axioms exist yet. So I left that out for now.

Copy link
Member

@jespercockx jespercockx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a great start! I've left two small comments.

lib/Haskell/Law/Num/Nat.agda Outdated Show resolved Hide resolved
lib/Haskell/Law/Num/Nat.agda Outdated Show resolved Hide resolved
@pmbittner pmbittner force-pushed the issue-108-Num branch 5 times, most recently from 6b4a2f5 to aa62b43 Compare June 10, 2024 12:33
This commit adds the new type class IsLawfulNum
that contains all the laws the Haskell Num
typeclass should satisfy.
There currently is one law we cannot formalize here
because toInteger is not yet part of our Prelude.

This commit is part of issue agda#108.
These functions were formerly private. They had to made accessible to other parts of the library to allow proofs, in particular for the IsLawfulNum instances. Both functions are still "hidden" in an "Internal" module though to signal these functions as not being intended to be used from any Haskell code.

This change also redefines subNat based on pattern-matching instead of
an if-else-expression with ltNat, to simplify proofs.
@pmbittner pmbittner marked this pull request as ready for review June 13, 2024 18:54
to make it visible for proofs
Haskell.Law.Num should publicly import all available instances
as well as the LawfulNum class. To avoid cyclic dependencies,
the functions for concluding number laws were move to
Haskell.Law.Num.Def.
@pmbittner
Copy link
Contributor Author

This PR is now ready to review.

Copy link
Member

@jespercockx jespercockx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, thank you very much!

@jespercockx jespercockx merged commit ec37285 into agda:master Jul 9, 2024
7 checks passed
@jespercockx jespercockx added this to the 1.3 milestone Sep 24, 2024
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.

2 participants