Zulip Chat Archive

Stream: general

Topic: definition of enat


Tomas Skrivan (Oct 29 2020 at 09:49):

Why is enat defined as roption nat? I was expecting the definition to be something like def enat := ℕ⊕unit. For example, I have tried to write function returning previous enat and after half an hour I gave up. With the definition def enat' := ℕ⊕unit it is simple:

def prev : enat'  enat'
| (sum.inl 0) := sum.inl 0
| (sum.inl (n+1)) := sum.inl n
| (sum.inr _) := sum.inr unit.star

with appropriate coercions and notations(e.g. ∞=sum.inr unit.star) this can be really easy on the eyes.

My conjecture is that enat is quite often a result of some decision process(decidable or not), so with the definition roption nat this decision is embedded inside of enat. I find this really strange and makes enat not user friendly when used purely as a constructive object.

Kevin Buzzard (Oct 29 2020 at 09:50):

I was expecting it to be option nat. roption is very hard for people who aren't "constructive-aware" (like me!) to work with, I agree.

Mario Carneiro (Oct 29 2020 at 09:58):

One way to write prev is roption.map nat.pred

Mario Carneiro (Oct 29 2020 at 10:00):

we could add (classical) enat.cases_on to partially address this, but lean is stingy about changing the default equation compiler logic so that's harder

Tomas Skrivan (Oct 29 2020 at 10:01):

option nat would be also fine. But with enat defined as roption nat I will probably just split every function in two to handle finite and infinite case. My use case is to define classes of finitely and infinitely differentiable functions.

Kevin Buzzard (Oct 29 2020 at 10:02):

One code block I find helpful for dealing with enat is docs#padic_val_rat

Kevin Buzzard (Oct 29 2020 at 10:03):

Here, Rob Lewis wants to define the p-adic valuation of a rational number, and he uses multiplicity to compute it, but multiplicity returns an enat. He deftly turns it into an integer using roption.get

Mario Carneiro (Oct 29 2020 at 10:04):

There is roption.to_option already to turn the roption into an option for case analysis

Mario Carneiro (Oct 29 2020 at 10:05):

but using roption directly encourages a style where you don't handle the infinity case separately but it's implied from the finite case

Mario Carneiro (Oct 29 2020 at 10:06):

Even if it was defined as an option, I wouldn't recommend casing on it because using none : enat is bound to cause type class inference problems because none literally has type option nat not enat

Mario Carneiro (Oct 29 2020 at 10:07):

instead, just apply a dedicated enat.cases_on lemma that can use the right idioms for the two cases

Mario Carneiro (Oct 29 2020 at 10:08):

and that way, the underlying definition does not have to be scrutinized, and so you won't even be able to tell if it's option or roption under the hood

Tomas Skrivan (Oct 29 2020 at 10:13):

It will take me some time to digest this and understand that roption is a more favorable design choice then option here. But thanks a lot for the explanation!

Mario Carneiro (Oct 29 2020 at 10:18):

whether it's actually more favorable overall is not clear, but it is clear that we don't want to leak API details so any operation that demonstrates the difference should probably be avoided

Gabriel Ebner (Oct 29 2020 at 10:23):

I also agree, it should be with_top nat.

Kevin Buzzard (Oct 29 2020 at 10:39):

I agree, I shouldn't really have mentioned option.

Yury G. Kudryashov (Oct 29 2020 at 10:39):

We already have CC^\infty functions, see docs#times_cont_diff_on

Yury G. Kudryashov (Oct 29 2020 at 10:40):

And this definition uses with_top nat

Tomas Skrivan (Oct 29 2020 at 10:57):

However they are defined only between normed spaces. I want the definition of conveniently smooth map between locally convex spaces.


Last updated: Dec 20 2023 at 11:08 UTC