Skip to content
This repository has been archived by the owner on Oct 14, 2023. It is now read-only.

Add monad laws #1485

Closed
wants to merge 19 commits into from
Closed

Add monad laws #1485

wants to merge 19 commits into from

Conversation

Kha
Copy link
Member

@Kha Kha commented Mar 24, 2017

  • add invariants to functor, applicative, and monad
  • default as many superclass laws as possible - when given only pure and bind, the proof obligations break down to just 1 functor law and 2 monad laws
  • prove non-meta instances correct, use undefined for meta ones
  • extend structure a bit to make things easier

The instance proofs aren't exactly pretty - I wildly switched between dsimp, simp, and rw depending on what worked in a given context.

I tried to fix io by constructing an unsafe monad instance in C++ via Lean, but there's still some VM error left. There are also a few other tests I have broken somehow.

@leodemoura
Copy link
Member

I tried to fix io by constructing an unsafe monad instance in C++ via Lean, but there's still some VM error left. There are also a few other tests I have broken somehow.

I will take a look.

leodemoura added a commit to leodemoura/lean that referenced this pull request Mar 24, 2017
@leodemoura
Copy link
Member

Fixed the io_monad

@leodemoura
Copy link
Member

The instance proofs aren't exactly pretty - I wildly switched between dsimp, simp, and rw depending on what worked in a given context.

I investigated some of your proofs. I can see it was not a smooth ride.
They expose problems with simp.
I found the source of the problem (higher order matching), but it is not an easy fix.
I will create a new wiki for describing a new matching algorithm for Lean.

leodemoura added a commit to leodemoura/lean that referenced this pull request Mar 24, 2017
…s used

see leanprover#1485

@Kha We need this commit to be able to execute commands such as:
```lean
  #check @monad.mk
```
cases x,
{ dsimp [option_t_bind._match_1, return, pure],
rw [monad.pure_bind], apply rfl },
{ apply rfl }
Copy link
Member

Choose a reason for hiding this comment

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

We have tactic.interactive.refl.

leodemoura added a commit to leodemoura/lean that referenced this pull request Mar 24, 2017
leodemoura added a commit to leodemoura/lean that referenced this pull request Mar 24, 2017
leodemoura added a commit to leodemoura/lean that referenced this pull request Mar 24, 2017
Kha added 2 commits March 25, 2017 10:47
… given fields as soon as possible, too.

Also make sure not to elaborate fields before other fields their type depends on.
Makes inline tactic proofs in structure instances possible.
Kha pushed a commit to Kha/lean that referenced this pull request Mar 25, 2017
Kha pushed a commit to Kha/lean that referenced this pull request Mar 25, 2017
…s used

see leanprover#1485

@Kha We need this commit to be able to execute commands such as:
```lean
  #check @monad.mk
```
Kha pushed a commit to Kha/lean that referenced this pull request Mar 25, 2017
@@ -29,7 +29,7 @@ class unfold_untrusted_macros_fn : public replace_visitor_with_tc {
expr r = update_macro(e, new_args.size(), new_args.data());
if (!m_trust_lvl || def.trust_level() >= *m_trust_lvl) {
if (optional<expr> new_r = m_ctx.expand_macro(r)) {
return *new_r;
return visit(*new_r);
} else {
Copy link
Member

Choose a reason for hiding this comment

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

BTW, this module will need to be re-implemented. It was already a performance bottleneck before this change.

@Kha
Copy link
Member Author

Kha commented Mar 25, 2017

Fixed the io_monad

Thanks! There is a last trust0 issue with macros in intro rules not being expanded, but I'm not sure where to best place a fix.

@leodemoura
Copy link
Member

There is a last trust0 issue with macros in intro rules not being expanded, but I'm not sure where to best place a fix.

Did the change at unfold_macros fixed the problem?
If yes, then keep it.
We will need to re-implement unfold_macros anyway in the future.
We already have performance problems in this module.
If the change did not fix the problem, then try to look for missing unfold_untrusted_macros calls at structure_cmd.cpp.

@Kha
Copy link
Member Author

Kha commented Mar 25, 2017

Sorry, I should have been more specific. I was looking for a catch-all location to place the call at, but I don't think there is one in library/. I'll add one just in structure_cmd for now.

@leodemoura
Copy link
Member

@Kha I have been trying to implement the "abstract nested proofs" feature. It was much harder than expected. I found many problems. I can list them if you are interested. Here is the compromise I implemented.

Proofs are abstracted in

  1. Regular definitions (i.e., no recursive equation) def f : T := v, where T is not a proposition, and it is not meta.

  2. Right hand side of equation lemmas (if its type is not a proposition). We use these equation lemmas for "unfolding" the definition. Example:

#check  @vector.append.equations._eqn_1

produces

∀ {α} {n m} l₁ h₁ l₂ h₂,  append ⟨l₁, h₁⟩ ⟨l₂, h₂⟩ = ⟨l₁ ++ l₂, append._main._proof_1 l₁ h₁ l₂ h₂⟩

Before this change, we would get

∀ {α} {n m} l₁ h₁ l₂ h₂,  append ⟨l₁, h₁⟩ ⟨l₂, h₂⟩ = ⟨l₁ ++ l₂, ... huge mess ...⟩

@cipher1024
Copy link
Contributor

In terms of design, is there a reason to have the functor, applicative and monad methods provided in the same classes as the laws? I find the layering of orders (i.e. has_le, weak_order, linear_weak_order, strict_order, etc) and arithmetic (has_add, add_semigroup, add_monoid, etc) very appealing and it makes them easier to use.

@leodemoura
Copy link
Member

@cipher1024 Are you suggesting we start with simple classes such as has_bind, has_map, has_seq, ... (similar to has_add, has_mul), and then we define monad, functor, etc on top of them?

BTW, we are planning to revise the algebraic hierarchy. If you have time, it would be great to have your feedback. The proposal is here: https://github.com/leanprover/lean/wiki/Refactoring-structures

@cipher1024
Copy link
Contributor

@leodemoura I was mostly referring to the separation that exists in the Lean library between the type classes with functions and the type classes with laws. I find it especially useful because, typically, when you define functions in terms of monads, what you really need is to have access to the bind operator, regardless of how it behaves. Later, when you prove something about the function, then you should assume that bind is associative, etc.

This being said, I like the idea of having the basic has_bind, has_map, has_seq, has_pure but only in so far as every new operator adds expressive power. For instance, I don't think that we should have has_seq_left or has_seq_right. I would rather make them a part of has_seq.

I'm thinking that the classes with laws could follow the hierarchy of the semigroupoids Haskell library with respect to Functor, Apply, Applicative, Bind and Monad.

BTW, thanks for linking me to the refactoring project. It looks exciting :) I'll contribute whatever feedback I can.

@Kha
Copy link
Member Author

Kha commented Mar 27, 2017

@leodemoura

Proofs are abstracted in

Regular definitions (i.e., no recursive equation) def f : T := v, where T is not a proposition, and it is not meta.

Right hand side of equation lemmas (if its type is not a proposition). We use these equation lemmas for "unfolding" the definition.

Nice, that sounds good enough. For default proofs in class decls, the _default definitions already act as abstraction, right?

@Kha
Copy link
Member Author

Kha commented Mar 27, 2017

@cipher1024

This being said, I like the idea of having the basic has_bind, has_map, has_seq, has_pure but only in so far as every new operator adds expressive power. For instance, I don't think that we should have has_seq_left or has_seq_right. I would rather make them a part of has_seq.

Sure, we can always add those (note that we already have has_bind). But I think it's a good idea that something called monad also has to fulfill the monad laws.

I'm thinking that the classes with laws could follow the hierarchy of the semigroupoids Haskell library with respect to Functor, Apply, Applicative, Bind and Monad.

Feel free to insert the missing classes into the hierarchy. I also haven't added laws to applicative yet, though it's not quite clear what those should be.

@Kha Kha changed the title [WIP] Add monad laws Add monad laws Mar 27, 2017
@spl
Copy link
Contributor

spl commented Mar 27, 2017

@Kha:

I also haven't added laws to applicative yet, though it's not quite clear what those should be.

I think you meant alternative there. :)

@Kha
Copy link
Member Author

Kha commented Mar 27, 2017

I think you meant alternative there. :)

Oh, right :) .

@johoelzl
Copy link
Contributor

@Kha it looks like we need a hierarchy of alternative type classes. What the Typeclassopedia article does not mention: how should map behave under <|>. (a weaker form of right distributivity) I would assume it distributes nicely map f (a <|> b) = (map f a) <|> (map f b). The problems mentioned in the article go away when the first part of seq is pure.

@leodemoura
Copy link
Member

Nice, that sounds good enough. For default proofs in class decls, the _default definitions already act as abstraction, right?

@Kha Yes, this is correct.

leodemoura added a commit to leodemoura/lean that referenced this pull request Mar 27, 2017
leodemoura added a commit to leodemoura/lean that referenced this pull request Mar 27, 2017
…s used

see leanprover#1485

@Kha We need this commit to be able to execute commands such as:
```lean
  #check @monad.mk
```
leodemoura added a commit to leodemoura/lean that referenced this pull request Mar 27, 2017
@leodemoura leodemoura closed this Mar 27, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants