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

Add Algebra interfaces and laws #242

Merged
merged 2 commits into from
Jul 4, 2020
Merged

Conversation

nickdrozd
Copy link
Contributor

This PR ports over some Algebra stuff from Idris 1. It is mostly similar: the interfaces are split into syntactic versions and verified versions. The latter are named like VMonoid etc. That can be changed, but I think it's the most ergonomic name.

Many of the theorems are stated but not proved. They can all be proved in Idris 1 [1], but the proofs don't work here. I would expect them all to work. There seem to be a few different bugs involved, but I don't understand the details.

[1] See https://github.com/idris-lang/Idris-dev/blob/master/libs/contrib/Control/Algebra/Laws.idr and idris-lang/Idris-dev#4848

@nickdrozd
Copy link
Contributor Author

I've included commented-out the proofs that I would expect to work, but don't. In some cases, the mirror image of the proof does work. For instance, this works:

cancelLeft : VGroup ty => (x, y, z : ty) ->
  x <+> y = x <+> z -> y = z
cancelLeft x y z p =
  rewrite sym $ monoidNeutralIsNeutralR y in
    rewrite sym $ groupInverseIsInverseR x in
      rewrite sym $ semigroupOpIsAssociative (inverse x) x y in
        rewrite p in
      rewrite semigroupOpIsAssociative (inverse x) x z in
    rewrite groupInverseIsInverseR x in
  monoidNeutralIsNeutralR z

But this doesn't:

cancelRight : VGroup ty => (x, y, z : ty) ->
  y <+> x = z <+> x -> y = z
cancelRight x y z p =
  rewrite sym $ monoidNeutralIsNeutralL y in
    rewrite sym $ groupInverseIsInverseL x in
      rewrite semigroupOpIsAssociative y x (inverse x) in
        rewrite p in
      rewrite sym $ semigroupOpIsAssociative z x (inverse x) in
    rewrite groupInverseIsInverseL x in
  monoidNeutralIsNeutralL z

Copy link
Contributor

@rgrover rgrover left a comment

Choose a reason for hiding this comment

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

In essence:

  • some of the commented sections may be un-necessary.
  • Idris2 appears to be unable to normalize straightforward equalities in some cases.
    I'm sorry I didn't go further with the proofs. I feel this is a valuable addition. All the best.

public export
inverseCommute : VGroup ty => (x, y : ty) ->
y <+> x = neutral {ty} -> x <+> y = neutral {ty}
-- inverseCommute x y p = selfSquareId (x <+> y) prop where
Copy link
Contributor

Choose a reason for hiding this comment

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

same as above. this can be uncommented.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Control/Algebra/Laws.idr:45:7--48:1:While processing right hand side of inverseCommute at Control/Algebra/Laws.idr:39:1--48:1:
While processing right hand side of inverseCommute,prop at Control/Algebra/Laws.idr:41:3--48:1:
Rewriting by neutral <+> ?ty x y p (\{rwarg:1434} => (rwarg = x <+> y)) (sym (semigroupOpIsAssociative x y (x <+> y))) (\{rwarg:1451} => (x <+> rwarg = x <+> y)) (semigroupOpIsAssociative y x y) (\{rwarg:1459} => (x <+> (rwarg <+> y) = x <+> y)) p = ?ty x y p (\{rwarg:1434} => (rwarg = x <+> y)) (sym (semigroupOpIsAssociative x y (x <+> y))) (\{rwarg:1451} => (x <+> rwarg = x <+> y)) (semigroupOpIsAssociative y x y) (\{rwarg:1459} => (x <+> (rwarg <+> y) = x <+> y)) p did not change type x <+> (neutral <+> y) = x <+> y

public export
selfSquareId : VGroup ty => (x : ty) ->
x <+> x = x -> x = neutral {ty}
-- selfSquareId x p =
Copy link
Contributor

Choose a reason for hiding this comment

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

Using Idris2 from 4aa1c1f, this definition, when uncommented, compiles for me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Using 6898965:

Control/Algebra/Laws.idr:33:7--35:1:While processing right hand side of selfSquareId at Control/Algebra/Laws.idr:28:1--35:1:
Can't solve constraint between:
	neutral
and
	inverse x <+> x

public export
groupInverseIsInverseL : VGroup ty => (x : ty) ->
x <+> inverse x = neutral {ty}
-- groupInverseIsInverseL x =
Copy link
Contributor

Choose a reason for hiding this comment

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

can be uncommented (see above)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Control/Algebra/Laws.idr:53:33--53:57:While processing right hand side of groupInverseIsInverseL at Control/Algebra/Laws.idr:52:1--55:1:
Can't solve constraint between:
	Constraint (Monoid ty) (Constraint (MonoidV ty) conArg)
and
	Constraint (Monoid ty) (Constraint (Group ty) conArg)

inverseSquaredIsIdentity : VGroup ty => (x : ty) ->
inverse (inverse x) = x
-- inverseSquaredIsIdentity x =
-- let x' = inverse x in
Copy link
Contributor

Choose a reason for hiding this comment

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

Idris2 isn't able to use x' = inverse x in its normalization. The following also reproduces the issue (the copiler complains about prf):

let x' = inverse x
    prf = the (x' = inverse x) Refl
 in ...

Copy link
Contributor

Choose a reason for hiding this comment

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

Based on what @edwinb suggested, we could aid Idris2 in the equality between x' and inverse x using a local function like:

||| -(-x) = x
public export
inverseSquaredIsIdentity : VGroup ty => (x : ty) ->
  inverse (inverse x) = x
inverseSquaredIsIdentity x =
  let
    lemma : (x' : ty) -> (x' = inverse x) -> inverse (inverse x) = x
    lemma x' prf =
      uniqueInverse
        x'
        (inverse (inverse x))
        x
        (rewrite sym prf in groupInverseIsInverseR x')
        (rewrite prf in groupInverseIsInverseR x)
   in lemma (inverse x) Refl

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I suggest we avoid leaning on workarounds like this. As a user, I don't want to have to work around quirks in the type system. Ideally I would be able to express what I want to express without feeling like I have to walk on eggshells to satisfy the typechecker.

Especially in this particular case, the existing proof is clean and elegant, and this change obscures that.

@edwinb
Copy link
Collaborator

edwinb commented Jun 6, 2020

Thanks for these. I'd like to take a look at the ones which fail before merging this, just to avoid having things with types but no definitions in the library.

Also some bikeshedding - I'm not sure about having the V as a prefix, my preference would be for a suffix for tab completion reasons. I expect there's as many opinions on naming as there are people, however...

@edwinb
Copy link
Collaborator

edwinb commented Jun 6, 2020

Actually it looks as if @rgrover has worked out all the problems, thanks for that! The let one is decribed here: https://idris2.readthedocs.io/en/latest/updates/updates.html#let-bindings

It's an annoyance, but better for overall consistency, with the core language as it stands.

@nickdrozd
Copy link
Contributor Author

@edwinb I changed VMonoid to MonoidV, etc.

@nickdrozd
Copy link
Contributor Author

@rgrover I wasn't able to get any of the proofs to go through locally. I uncommented the proofs and pushed to see how the CI would react. It has failed, but I can't see the output.

@nickdrozd
Copy link
Contributor Author

I got rid of all the let bindings and uncommented the proofs (except for inverseOfSum, which I couldn't get to go through). There are no holes left, so unless anyone has any objections this should be good to go.

@edwinb
Copy link
Collaborator

edwinb commented Jul 4, 2020

Sorry, this has been lingering for a while - everything looks fine to me though. Thanks for the contribution!

@edwinb edwinb merged commit 9d1bb82 into idris-lang:master Jul 4, 2020
attila-lendvai pushed a commit to attila-lendvai-patches/Idris2 that referenced this pull request Jul 27, 2021
@nickdrozd nickdrozd deleted the algebra branch August 9, 2021 15:58
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