Zulip Chat Archive

Stream: new members

Topic: Bundled and unbundled


Eric Wieser (Jun 30 2020 at 09:11):

What exactly do "bundled" and "unbundled" mean in the context of lean? Is there a [Note: ...] or manual pages somewhere that summarizes how to choose between them when designing structure?

I've seen some posts here suggesting that extends another_type_class is a bundled type class and [another_type_class] is an unbundled one. I've seem some other discussions suggesting that struct is bundled and class is unbundled.

Is this a mathematics term that I'm unfamiliar with, or a lean concept?

Johan Commelin (Jun 30 2020 at 09:12):

It's not maths. It's about the amount of things that you package into your structure vs keeping them as arguments.

Eric Wieser (Jun 30 2020 at 09:13):

The version with more things in the structure is considered the bundled one?

Eric Wieser (Jun 30 2020 at 09:40):

As for my second point then, is there anything in the lean / mathlib docs about how those choices are made internally? In particular, how there seem to be large swathes of deprecated "unbundled" code - it would be nice to learn and apply the same rationale elsewhere

Mario Carneiro (Jun 30 2020 at 09:48):

The deprecated directory primarily contains unbundled homs, which have been discussed on Zulip many times before

Mario Carneiro (Jun 30 2020 at 09:48):

We're trying to move away from [is_group_hom (f : G -> H)] to (f : G ->* H)

Eric Wieser (Jun 30 2020 at 09:51):

Is there anything I can read to understand the motivation? Perhaps some notable zulip threads?
(I'm not saying I disagree with it, I just want to avoid making the same mistake in my own code)

Mario Carneiro (Jun 30 2020 at 09:52):

The plan has been around for so long (more than a year) that it's tricky finding a good reference

Mario Carneiro (Jun 30 2020 at 09:52):

https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/How.20to.20handle.20transfer.20to.20bundled.20homs

Jalex Stark (Jun 30 2020 at 09:53):

I feel like I gained some clarity on these things by reading the mathlib paper

Mario Carneiro (Jun 30 2020 at 09:54):

https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/bundling.20mul_homs

Utensil Song (Jun 30 2020 at 15:01):

image.png

Utensil Song (Jun 30 2020 at 15:02):

We primarily use semi-bundled definitions for type classes in mathlib, with all operations being bundled except for the carrier types.

Utensil Song (Jul 01 2020 at 02:21):

When entering the bundled world, I wonder if we need to worry about the old/new or nested/flat structure thing at this stage? I felt reluctant to enter the bundled world ( and using inheritance ) because I read about these technical issues, and they don't look pretty or natural when reading the code in mathlib. And my goal was to make Lean code look like ordinary math as much as possible.

Also, I can't tell when to worry about lower instance priority either.

Kevin Buzzard (Jul 01 2020 at 06:40):

The linter will tell you about instance priority issues. And you will have to make a decision about old/new structures, but it's one decision per structure. The general rule of thumb is to make everything an old structure. The changes were made because of a scaling issue which we don't really see in mathematical structures so a lot of mathlib still uses old structures

Utensil Song (Jul 01 2020 at 14:20):

It seems a whole lot of algebra stuff in mathlib is using the new structure (nested) and my code heavily relies on algebra part so I might stay new for now. And it frightens me that old structures struggle to extend new structures (https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/DVRs/near/200764626).

Eric Wieser (Jul 01 2020 at 15:22):

Kinda related to this conversation - can a type class be fully unbundled (have no fields)?

Kevin Buzzard (Jul 01 2020 at 15:23):

There are typeclasses which extend other classes and have no fields.

Kevin Buzzard (Jul 01 2020 at 15:24):

class comm_ring (α : Type u) extends ring α, comm_semigroup α

(that's it)

Eric Wieser (Jul 01 2020 at 15:25):

Is class comm_ring (α : Type u) [ring α] [comm_semigroup α] legal?

Kevin Buzzard (Jul 01 2020 at 15:25):

I should think so.

Kevin Buzzard (Jul 01 2020 at 15:27):

But then if you wanted a commutative ring you'd have to write [ring R] [comm_semigroup R] [comm_ring R]

Eric Wieser (Jul 01 2020 at 15:30):

You've predicted exactly the trouble I was about to run into

Eric Wieser (Jul 01 2020 at 15:31):

What's the rule for picking between class comm_ring (α : Type u) extends ring α and class comm_ring (α : Type u) := (r : s ring α)?

Kevin Buzzard (Jul 01 2020 at 15:32):

This is a computer science question. I don't really understand these issues properly at all.

Eric Wieser (Jul 01 2020 at 15:32):

Seems in my case that only the latter is legal, so lets try that approach

Kevin Buzzard (Jul 01 2020 at 15:34):

Once you've actually got your use case compiling, you might want to run it past the people in #maths to see what the experts think of it. (me doing this last week)

Eric Wieser (Jul 01 2020 at 15:40):

Good idea, thanks

Eric Wieser (Jul 01 2020 at 15:41):

On the note of compiling... If there's one type class argument that lean is having trouble inferring, can I specify it explicitly without having to insert a tonne of placeholders to pad all the arguments that lean guesses correctly?

Bryan Gin-ge Chen (Jul 01 2020 at 15:42):

Not in Lean 3 as far as I know, but there's hope that the syntax for this will be better in Lean 4.

Kevin Buzzard (Jul 01 2020 at 15:42):

You only have to pad the ones to the left of the one that Lean had trouble inferring.

Eric Wieser (Jul 01 2020 at 15:43):

How do I deal with cases where lean wants a ring R but I have comm_ring R?

Kevin Buzzard (Jul 01 2020 at 15:43):

But there are other workarounds. For example haveI or letI in tactic mode.

Kevin Buzzard (Jul 01 2020 at 15:43):

If you have a comm_ring, Lean's type class inference system should have no trouble inferring the ring structure.

Eric Wieser (Jul 01 2020 at 15:43):

type mismatch at application
  module (A 0) G
term
  graded_algebra_components.zc
has type
  comm_ring (A 0)
but is expected to have type
  ring (A 0)

Eric Wieser (Jul 01 2020 at 15:44):

I've had to pass the type class explicitly because I was attempting to bundle it

Kevin Buzzard (Jul 01 2020 at 15:44):

That's not what I interpreted your question as meaning

Kevin Buzzard (Jul 01 2020 at 15:44):

import tactic

example (R : Type) [comm_ring R] : ring R := by apply_instance

Eric Wieser (Jul 01 2020 at 15:45):

I'm taking about the first question in combination with the second one

Kevin Buzzard (Jul 01 2020 at 15:45):

This is xy. You shouldn't be passing explicit proofs that something is a ring. The whole point of the type class inference system is to do this for you.

Eric Wieser (Jul 01 2020 at 15:46):

This is "what happens if I try what I asked in https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/Bundled.20and.20unbundled/near/202583368"

Kevin Buzzard (Jul 01 2020 at 15:46):

The answer to the question you asked is to run that example above but instead give it a name and then #print it so you know what the function which eats a comm_ring and spits out a ring is called.

Kevin Buzzard (Jul 01 2020 at 15:46):

But the real issue is that nobody should need to know the name of that function, so if you need to know it then there is something more fundamentally wrong

Kevin Buzzard (Jul 01 2020 at 15:47):

Type class inference will fill in that field, and if it doesn't, then don't fill it in manually, but instead figure out why it didn't, and fix the actual problem

Kevin Buzzard (Jul 01 2020 at 15:49):

Eric Wieser said:

This is "what happens if I try what I asked in https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/Bundled.20and.20unbundled/near/202583368"

There is a typo in what you posted (a random s) but assuming it's not supposed to be there then instead of the round brackets you should make them square brackets, and you might have to manually tag the structure projection with @[instance]

Kevin Buzzard (Jul 01 2020 at 15:49):

What I'm saying is that the infrastructure is there, I believe, to make the set-up work.

Eric Wieser (Jul 01 2020 at 15:51):

The full repro is:

class graded_algebra_components
  -- a type for each grade.
  (A :   Type u)
:=
  -- (A 0) is the scalar type
  [zc: comm_ring (A 0)]

  -- all the types form commutative vector spaces
  [b:  n, add_comm_group (A n)]
  [c:  n, module (A 0) (A n)]


class graded_algebra_hom
  (A :   Type u) (G: Type u)
  [g : graded_algebra_components A]
  [add_comm_group G]
  [@module (A 0) G begin haveI r := g.zc, apply_instance end _] :=
(to_fun : n, A n [A 0] G)

Your apply_instance and haveI tip was enough to get it to compile, thanks

Kevin Buzzard (Jul 01 2020 at 15:51):

import tactic

universe u

class comm_ring' (α : Type u) :=
[r : ring α]

#print prefix comm_ring'

attribute [instance] comm_ring'.r

example (R : Type) [comm_ring' R] : ring R := by apply_instance -- works

Eric Wieser (Jul 01 2020 at 15:52):

Oh nice

Eric Wieser (Jul 01 2020 at 15:52):

Thanks!

Eric Wieser (Jul 01 2020 at 15:52):

Is there an inline syntax for that?

Eric Wieser (Jul 01 2020 at 15:53):

That solves my problem perfectly

Kevin Buzzard (Jul 01 2020 at 15:57):

I don't know an inline syntax -- you mean making zc (and b and c) an instance whilst defining graded_algebra_components? I don't know.

Eric Wieser (Jul 01 2020 at 15:57):

Yeah, some kind of @[instance] marker


Last updated: Dec 20 2023 at 11:08 UTC