Zulip Chat Archive
Stream: general
Topic: partial functions
Victor Porton (Jul 07 2018 at 15:43):
Why this does not work?
-- Switch from a function on a subset to a function to option monad
def subfunc_to_option {α β: Type} {c: α → Prop} (f: {x:α // c x} → β) : α → option β :=
λ y: α, if c y then some (f (subtype.mk y (arbitrary (c y) [true_inhabited (c y)]))) else none
Kenny Lau (Jul 07 2018 at 15:43):
put [decidable_pred c] in the list of assumptions (before the colon)
Victor Porton (Jul 07 2018 at 15:45):
Kenny, I did what you say. Moreover open classical
is already in effect. But it does not work now too
Chris Hughes (Jul 07 2018 at 15:53):
def subfunc_to_option {α β: Type} {c: α → Prop} [decidable_pred c] (f: {x:α // c x} → β) : α → option β := λ y: α, if h : c y then some (f (subtype.mk y h)) else none
Chris Hughes (Jul 07 2018 at 15:55):
if h : c y
instead of if c y
gives you access to the proof.
Victor Porton (Jul 07 2018 at 15:56):
Chris, Thanks it works now. But I am curious why my old code (with arbitrary
) didn't work.
Chris Hughes (Jul 07 2018 at 15:57):
Because there was no way of telling that the type c y
was inhabited.
Chris Hughes (Jul 07 2018 at 15:59):
It's actually very unusual to use inhabited
on Props.
Chris Hughes (Jul 07 2018 at 16:00):
Also open classical
only opens the classical namespace, it doesn't give you decidability. You need local attribute [instance] classical.prop_decidable
for that.
Victor Porton (Jul 07 2018 at 16:11):
I tried to synthesize the function in another direction. Now I know where is my error but don't know how to fix it:
-- Switch from function to option monad to a function on a subset
def option_to_subfunc {α β: Type} (f: α → (option β)) :=
λ y: {x:α // f x ≠ none},
match f y with
| some x := y
| none := sorry
Chris Hughes (Jul 07 2018 at 16:15):
You needed to give the type, and write end
at the end of your match
def option_to_subfunc {α β: Type} (f: α → (option β)) : {x : α // f x ≠ none} → {x:α // f x ≠ none} := λ y: {x:α // f x ≠ none}, match f y with | some x := y | none := sorry end
Johan Commelin (Jul 07 2018 at 16:15):
@Victor Porton If you surround your code between three backticks, then it will be typeset in a codeblock. If you append "lean" to the first 3 backticks, then it will get highlighting!
Kevin Buzzard (Jul 07 2018 at 16:16):
Again f y
does not make sense because alpha is not equal to the subtype you are using. f wants an input of type alpha and you are feeding it y
. Did you read about subtypes in Theorem in Lean?
Victor Porton (Jul 07 2018 at 16:16):
@Chris Hughes Your code does not validate. What I really wanted to ask is what to do instead of sorry
. I am lost about this
Chris Hughes (Jul 07 2018 at 16:17):
It does make sense because there's a coercion
Victor Porton (Jul 07 2018 at 16:17):
Yes, I knew that here there is a coercion
Kevin Buzzard (Jul 07 2018 at 16:17):
Oh -- it does make sense in this context because there's a coercion!
Kevin Buzzard (Jul 07 2018 at 16:17):
:-)
Chris Hughes (Jul 07 2018 at 16:21):
In response to a question in (no topic) that should have been here.
def option_to_subfunc {α β: Type} (f: α → (option β)) : {x : α // f x ≠ none} → {x:α // f x ≠ none} := λ y: {x:α // f x ≠ none}, have hfy : f y ≠ none := y.2, match f y, hfy with | some x := λ hfy, y | none := λ hfy, (hfy rfl).elim end
Victor Porton (Jul 07 2018 at 16:25):
@Chris Hughes 1. The values type of your option_to_subfunc
is wrong; it should be \beta
not {x:α // f x ≠ none}
. 2. Do I understand correctly that the values in have
are "ignored" (not included into the result) when building the value of the defined object? 3. What this elimination do? (I am a very novice and understand your code partially.)
Victor Porton (Jul 07 2018 at 16:26):
@Chris Hughes Sorry for a stupid question but I do not understand what :=
after have
means
Chris Hughes (Jul 07 2018 at 16:27):
It's the same as from
Victor Porton (Jul 07 2018 at 16:27):
I am trying to read your code
Victor Porton (Jul 07 2018 at 16:29):
Sorry, what is λ hfy, y
?
Chris Hughes (Jul 07 2018 at 16:29):
I put hfy
after the match
so I would have access to the fact that f y ≠ none
. In the none
cases hfy
has type none ≠ none
which is obviously false, so I can use false.elim
to define the function
Chris Hughes (Jul 07 2018 at 16:30):
hfy
is just a proof that f y = none
or in the some
case that some ≠ none
Chris Hughes (Jul 07 2018 at 16:32):
I think this is the function you want
def option_to_subfunc {α β: Type} (f: α → (option β)) : {x : α // f x ≠ none} → β := λ y: {x:α // f x ≠ none}, have hfy : f y ≠ none := y.2, match f y, hfy with | some x := λ hfy, x | none := λ hfy, (hfy rfl).elim end
Victor Porton (Jul 07 2018 at 16:33):
what is (hfy rfl).elim
?
Chris Hughes (Jul 07 2018 at 16:33):
match f y, hfy with
means I now have to define a function with type Π x : option β, x ≠ none → β
Chris Hughes (Jul 07 2018 at 16:34):
hfy rfl
is a proof of false
Chris Hughes (Jul 07 2018 at 16:34):
(hfy rfl).elim
is another way of writing false.elim (hfy rfl)
.
Victor Porton (Jul 07 2018 at 16:35):
I need to time to review all you wrote
Chris Hughes (Jul 07 2018 at 16:35):
false.elim
is a function that gives you a term of any type given a proof of false
Victor Porton (Jul 07 2018 at 16:39):
What I don't understand: Why is it | some x := λ hfy, x
not | some x := x
. It should be a value in \b
, right? But λ hfy, x
is a function and so it looks for me that it can't be in \b
Victor Porton (Jul 07 2018 at 16:39):
err.. wrong
Chris Hughes (Jul 07 2018 at 16:43):
match f y, hfy
with means I now have to define a function with type Π x : option β, x ≠ none → β
, not option β → β
any more. Even though I'm not using the fact that x ≠ none
in the some
case, I still have access to it.
Victor Porton (Jul 07 2018 at 16:46):
Hm, it is harder than I expected, I yet do not understand the details of this simple construct. I initially started to learn Lean to rewrite my English book in Lean. Now I suspect that it would take me too much time to master Lean. What is your advice: learn Lean or just to keep writing math in English?
Chris Hughes (Jul 07 2018 at 16:47):
What field of maths is your book on?
Chris Hughes (Jul 07 2018 at 16:48):
I think maybe a good way to think about the function is that the output of type β
is the function of type Π x : option β, x ≠ none → β
applied to f y
and hfy
Victor Porton (Jul 07 2018 at 16:48):
@Chris Hughes I discovered a new subfield of general topology (though some man expressed that he does not consider it a subfield of general topology). For example the formula $f\circ\mu \leq \nu\circ f$ means that $f$ is a continuous morphisms from $\mu$ to $\nu$.
Chris Hughes (Jul 07 2018 at 16:50):
I don't really know much about topology (I'm a first year undergraduate). I think @Patrick Massot and @Johannes Hölzl know about topology in lean.
Victor Porton (Jul 07 2018 at 16:50):
Honestly, I am somehow lost in your Lean discussion. I may re-read it again
Victor Porton (Jul 07 2018 at 16:51):
@Chris Hughes This does not matter, as I build my version of topology from scratch, without using the classical GT
Victor Porton (Jul 07 2018 at 16:54):
Is match f y, hfy
the same as match \<f y, hfy\>
?
Chris Hughes (Jul 07 2018 at 17:01):
more or less
def option_to_subfunc {α β: Type} (f: α → (option β)) : {x : α // f x ≠ none} → β := λ y: {x:α // f x ≠ none}, have hfy : f y ≠ none := y.2, match (⟨f y, hfy⟩ : Σ' x : option β, x ≠ none) with | ⟨some x, hfy⟩ := x | ⟨none, hfy⟩ := (hfy rfl).elim end
Chris Hughes (Jul 07 2018 at 17:03):
I think that might be more confusing though.
Victor Porton (Jul 07 2018 at 17:06):
It seems that I do (or almost do) understand your last ("more confusing") code. But why the "less confusing" code (which I don't understand) uses some x := λ hfy, x
not some x := x
?
Victor Porton (Jul 07 2018 at 17:06):
oh, it seems I got the idea
Victor Porton (Jul 07 2018 at 17:09):
I have yet a question. How does the following work?
match f y, hfy with | some x := λ hfy, x | none := λ hfy, (hfy rfl).elim end
We have two expressions in match
arguments and just one in the math conditions. How do they match?
Chris Hughes (Jul 07 2018 at 17:16):
I don't really understand enough about the equation compiler to answer the question properly.
Victor Porton (Jul 07 2018 at 17:17):
@Chris Hughes Anyway much thanks for your support. Also what does $\Sigma'$ mean? It has added apostrophe
Victor Porton (Jul 07 2018 at 17:18):
Now I "almost" understand. Thanks
Chris Hughes (Jul 07 2018 at 17:18):
It's just like Sigma, except the constructors can be either proofs or data, whereas Sigma only takes data.
Chris Hughes (Jul 07 2018 at 17:22):
This is perhaps a better way of writing the function
def option_to_subfunc {α β: Type} (f: α → (option β)) : {x : α // f x ≠ none} → β := λ y : {x:α // f x ≠ none}, let g : Π x : option β, x ≠ none → β := λ x, match x with | (some x) := λ h, x | none := λ h, (h rfl).elim end in g (f y) y.property
Victor Porton (Jul 07 2018 at 17:23):
@Chris Hughes It gets better as I rewrote it more understandably
def option_to_subfunc {α β: Type} (f: α → (option β)) : {x : α // f x ≠ none} → β := λ y: {x:α // f x ≠ none}, have hfy : f y ≠ none := y.2, match f y, hfy with | some x, hfy := x | none , hfy := (hfy rfl).elim end
Victor Porton (Jul 07 2018 at 17:24):
I don't understand your last code. For example, what is property
?
Chris Hughes (Jul 07 2018 at 17:25):
Another way of writing y.2
Victor Porton (Jul 07 2018 at 17:26):
Why do you think the the second way is better?
Chris Hughes (Jul 07 2018 at 17:30):
I had to try out a few things to get the first way to work. For example this didn't work. I don't really have a good reason why the second way is better other than that.
def option_to_subfunc {α β: Type} (f: α → (option β)) : {x : α // f x ≠ none} → β := λ y: {x:α // f x ≠ none}, match f y, y.2 with | some x, hfy := x | none , hfy := (hfy rfl).elim end
Chris Hughes (Jul 07 2018 at 17:33):
It's clearer what's going on, because in the first method, it's not obvious that hfy will have type some x ≠ none
or none ≠ none
, and not f y ≠ none
in the match expression.
Mario Carneiro (Jul 07 2018 at 18:10):
In that last one, y.2
has the type f y.1 ≠ none
, so it is important that you write f y.1
instead of f (\u y)
Patrick Massot (Jul 07 2018 at 18:26):
What about
def option_to_subfunc {α β: Type} (f: α → (option β)) : {x : α // option.is_some (f x)} → β | ⟨x, h⟩ := option.get h
Chris Hughes (Jul 07 2018 at 18:27):
I thought the function probably already existed, but I couldn't find it.
Patrick Massot (Jul 07 2018 at 18:27):
option.is_some
is directly about what you care about instead of its negation
Patrick Massot (Jul 07 2018 at 18:28):
I don't know if it already exists
Chris Hughes (Jul 07 2018 at 18:30):
I think I saw it before, but I was thrown off by the fact is_some
is bool
rather than Prop
Patrick Massot (Jul 07 2018 at 18:30):
Oh, you mean is_some
already existed.
Patrick Massot (Jul 07 2018 at 18:31):
I thought you were referring to option_to_subfunc
Chris Hughes (Jul 07 2018 at 18:32):
I was referring to option_to_subfunc
or things like it, and I saw option.get
but I didn't like it because is_some
is bool
Victor Porton (Jul 07 2018 at 20:02):
@Patrick Massot What is this |
?
Victor Porton (Jul 07 2018 at 20:03):
@Patrick Massot Oh, it is pattern matching, I got
Victor Porton (Jul 07 2018 at 20:12):
weird, I can't find def option
in Lean library
Victor Porton (Jul 07 2018 at 20:12):
got: inductive option
Victor Porton (Jul 07 2018 at 20:14):
@Patrick Massot Where is option.get
defined?
Victor Porton (Jul 07 2018 at 20:15):
found: basic.lean
Victor Porton (Jul 07 2018 at 20:22):
I also don't understand (hfy rfl).elim
. Does it contain hfy
applied to rfl
? I would be not surprised if rfl
were applied to an equality, but I see inequality applied to rfl
what looks for me the "opposite" of what can be done. What is it?
Chris Hughes (Jul 07 2018 at 20:26):
hfy
has type none ≠ none
which is definitionally equal to none = none → false
. rfl
is a proof that none = none
so hfy rfl
has type false
Victor Porton (Jul 07 2018 at 21:46):
How having a function f
determine its domain?
Kenny Lau (Jul 07 2018 at 21:46):
it's in the type of the function
Victor Porton (Jul 07 2018 at 21:47):
@Kenny Lau So use match
?
Victor Porton (Jul 07 2018 at 21:47):
I have f: (Σ c:α → Prop, {x:α // c x})
and want to get the c
Kenny Lau (Jul 07 2018 at 21:48):
I... don't think that's how this works
Victor Porton (Jul 07 2018 at 21:48):
What I try is like:
noncomputable def subfunc_to_option2 {α β: Type} --[decidable_pred c] (f: (Σ c:α → Prop, {x:α // c x}) → β) : α → option β := λ y: α, if h : f.1 y then some (f (subtype.mk y h)) else none
Victor Porton (Jul 07 2018 at 21:52):
is this possible?
Victor Porton (Jul 07 2018 at 22:11):
This does not compile (types of sides equality in inv1
do not match). How to fix the error?
local attribute [instance] classical.prop_decidable -- Switch from a function on a subset to a function to option monad noncomputable def subfunc_to_option {α β: Type} {c: α → Prop} --[decidable_pred c] (f: {x:α // c x} → β) : α → option β := λ y: α, if h : c y then some (f (subtype.mk y h)) else none -- Switch from function to option monad to a function on a subset def option_to_subfunc {α β: Type} (f: α → (option β)) : {x : α // option.is_some (f x)} → β | ⟨x, h⟩ := option.get h theorem inv1 {α β: Type} {c: α → Prop} (f) : option_to_subfunc (@subfunc_to_option α β c f) = f := sorry
Chris Hughes (Jul 07 2018 at 22:12):
I'm not sure what you're trying to do. I don't think the type of f
is what you want it to be. You cannot do f.1
because f
is not a sigma type.
Victor Porton (Jul 07 2018 at 22:14):
@Chris Hughes I tried to eliminate {c: α → Prop}
from my definition. I tried it for completeness, but probably the proper way to do it is using an implicit argument (as in your code) instead
Victor Porton (Jul 07 2018 at 22:14):
@Chris Hughes Note that the issue in my very last question was different
Victor Porton (Jul 07 2018 at 22:19):
Side question: I subscribed to desktop notifications for this chat, but I get no notifications. Will I receive the notifications, if I close the browser window?
Chris Hughes (Jul 07 2018 at 22:21):
One way to fix the error is to use ==
instead of =
which allows you to state equality when the types are different (your types are different, but they should be equal). This can be unwieldy however. Another way would be to prove that they are equal when applied to an argument, something like this
theorem inv1 {α β: Type} {c: α → Prop} (f: {x:α // c x} → β) [decidable_pred c] : ∀ y : {x // c x}, option_to_subfunc (@subfunc_to_option α β c _ f) ⟨y.1, sorry⟩ = f y := sorry
Victor Porton (Jul 07 2018 at 22:23):
@Chris Hughes "unwieldy"? What is particularly bad with ==
? the second way (to write y
explicitly) seems even worse for me.
Victor Porton (Jul 07 2018 at 22:35):
Can the following be proved?
theorem eq_xxx (t: Type) (a b: t) := (a==b -> a=b)
(that is if values of the same type are ==
then they are =
)
Chris Hughes (Jul 07 2018 at 22:55):
eq_of_heq
Mario Carneiro (Jul 07 2018 at 22:58):
@Victor Porton You should receive notifications if you are directly addressed, like this
Victor Porton (Jul 07 2018 at 23:00):
hm, it looks now I am really stalled to fill the sorry
ies in my source:
local attribute [instance] classical.prop_decidable -- Switch from a function on a subset to a function to option monad noncomputable def subfunc_to_option {α β: Type} {c: α → Prop} --[decidable_pred c] (f: {x:α // c x} → β) : α → option β := λ y: α, if h : c y then some (f (subtype.mk y h)) else none -- Switch from function to option monad to a function on a subset def option_to_subfunc {α β: Type} (f: α → (option β)) : {x : α // option.is_some (f x)} → β | ⟨x, h⟩ := option.get h theorem inv1 {α β: Type} {c: α → Prop} (f) : option_to_subfunc (@subfunc_to_option α β c f) == f := sorry theorem inv2 {α β: Type} {c: α → Prop} (f): subfunc_to_option (@option_to_subfunc β α f) = f := sorry
How to learn to use ==
? Maybe I should read Coq docs on this?
Mario Carneiro (Jul 07 2018 at 23:01):
To address the larger goal of the definitions you are making, I think you want to use roption
(in data.pfun
) and the isomorphism theorems between roption
and option
. A function A -> roption B
is the same as a partial function (from a subset of A
to B
)
Victor Porton (Jul 08 2018 at 13:16):
@Mario Carneiro First, how roption
would be better for my purposes than option
? My project uses classical logic. (However someone suggested me to mark which theorems need axiom of choice explicitly.) Now we have three isomorphic objects (and thus three isomorphisms): a partial function, A->option B
and A->roption B
. I do not see how it could be better than my initial idea.
Mario Carneiro (Jul 08 2018 at 17:01):
Because a function A -> roption B
is a "subfunc" as you call it. It is literally a pair of a domain and a partial function on that domain
Mario Carneiro (Jul 08 2018 at 17:02):
so you can leverage the proofs of isomorphism there to obtain an isomorphism from A -> option B
to a partial function
Victor Porton (Jul 08 2018 at 17:05):
@Mario Carneiro Either you don't understand me, or I do not understand you. The "subfunc" by definition is a function on a _subtype_ of A
. But A -> roption B
is a function on the type A
, not on its arbitrary subtype as I want. It may be isomorphic, but they are _not_ the same.
Mario Carneiro (Jul 08 2018 at 17:05):
The isomorphism is almost trivial though, unlike the one from option
Mario Carneiro (Jul 08 2018 at 17:06):
And furthermore there is already a definition which gives this isomorphism, as_subtype
Victor Porton (Jul 08 2018 at 17:15):
@Mario Carneiro Thanks. As there is undocumented things like ==
which I may need for my Lean-related project, I prefer to lay it aside for an indefinite future. Moreover, I am going to lay aside abstract math research and get busy myself writing a free Python program (for an applied computer science, not abstract mathematics) now
Mario Carneiro (Jul 08 2018 at 17:15):
It's not undocumented, but it's a pain to work with
Last updated: Dec 20 2023 at 11:08 UTC