Zulip Chat Archive

Stream: mathlib4

Topic: Porting Data.String.Basic


Richard Osborn (Dec 01 2022 at 01:55):

I had a quick look at Data.String.Basic, and it seems that Data.String.Defs was only partially ported. Is the plan to finish porting the missing definitions in that file? I have also noticed that Control.Monad.Writer was partially ported as Control.Writer. Should Control.Monad.Writer now import Control.Writer?

Scott Morrison (Dec 01 2022 at 02:02):

When Control.Monad.Writer is fully ported, we should just delete Control.Writer (I'm presuming there is no control.writer in mathlib3).

Arien Malec (Dec 01 2022 at 02:05):

I suspect that a good chunk of Data.String.Basic is going to be #alignd away to Std

Jakob von Raumer (Dec 05 2022 at 09:54):

I've started to work on Data.String.Basic. There's the issue that the new implementation of Iterator looks completely different under the hood and it seems harder to prove anything about it

Jakob von Raumer (Dec 05 2022 at 10:15):

Also, I'm not really sure why the file adds an additional instance of LT String

Jakob von Raumer (Dec 05 2022 at 11:35):

The same goes for properties of evyerthing that's built on top of String.extract which now uses an external function and UTF8 byte indices. So to prove anything meaningful about these String operations would require a whole stack of helper lemmas

Mario Carneiro (Dec 05 2022 at 15:22):

Those helper lemmas sound like something to be added to std

Jakob von Raumer (Dec 05 2022 at 16:42):

The only place where the stuff in Data.String.Basic is needed, is Data.Buffer.Parser.Basic of which I'm not sure if it's well-portable either

Arien Malec (Dec 05 2022 at 21:37):

Scott Morrison said:

When Control.Monad.Writer is fully ported, we should just delete Control.Writer (I'm presuming there is no control.writer in mathlib3).

I'm looking at Control.Monad.Writer -- do I want to move code from Control.Writer here?

Arien Malec (Dec 05 2022 at 21:38):

i.e., as part of the single PR?

Scott Morrison (Dec 05 2022 at 23:34):

I think that would be fine.

Jakob von Raumer (Dec 15 2022 at 16:09):

Made a new PR for this: mathlib4#1054

Jakob von Raumer (Dec 15 2022 at 16:09):

Some stuff involving Iterator, String.popn and String.head still missing

Arien Malec (Dec 15 2022 at 16:55):

This reminds me that I keep going back to the proofs in Control.Monad.Writer and getting stuck.

Happy to unwind the PR here.

Jakob von Raumer (Dec 16 2022 at 09:45):

So the one thing I'm stuck at is to prove that Iterator.hasNext { s := { data := hd :: tl }, i := 0 } holds

Bulhwi Cha (Mar 18 2023 at 03:20):

I'm trying to rewrite the proof of String.lt_iff_toList_lt from the beginning, but I'm stuck on the following goal:

case cons.cons.inl
c₁ : Char
cs₁ : List Char
ih :  (l₂ : List Char), ltb { s := { data := cs₁ }, i := 0 } { s := { data := l₂ }, i := 0 } = true  cs₁ < l₂
cs₂ : List Char
 ltb { s := { data := c₁ :: cs₁ }, i := { byteIdx := csize c₁ } }
    { s := { data := c₁ :: cs₂ }, i := { byteIdx := csize c₁ } } =
  ltb { s := { data := cs₁ }, i := 0 } { s := { data := cs₂ }, i := 0 }

The above goal is the tactic state of the sorry in my proof:

String.lt_iff_toList_lt

Jakob von Raumer said:

The same goes for properties of evyerthing that's built on top of String.extract which now uses an external function and UTF8 byte indices. So to prove anything meaningful about these String operations would require a whole stack of helper lemmas

I don't know whether I should create a new git branch because I'm attempting not to use these helper lemmas to prove String.lt_iff_toList_lt.

Bulhwi Cha (Mar 20 2023 at 11:52):

I've managed to prove String.lt_iff_toList_lt. This theorem took me over 30 hours to prove. I'll soon push my commit to the git branch.

It's my first time porting a Mathlib file, and I think I picked the wrong one for a novice. :smiling_face_with_tear:

String.lt_iff_toList_lt

Eric Wieser (Mar 20 2023 at 15:40):

Why did you choose to rewrite it from scratch?

Bulhwi Cha (Mar 20 2023 at 22:02):

The previous proof didn't work, and its comment said, "TODO This proof probably has to be completely redone."

Bulhwi Cha (Mar 20 2023 at 22:15):

Jakob von Raumer said:

I've started to work on Data.String.Basic. There's the issue that the new implementation of Iterator looks completely different under the hood and it seems harder to prove anything about it

I had to prove several new theorems and lemmas because the definition of String.Iterator in Mathlib4 was different from that of Mathlib3.

Eric Wieser (Mar 20 2023 at 22:24):

docs4#String.Iterator, docs#string.iterator

Eric Wieser (Mar 20 2023 at 22:34):

Does it help to define String.Iterator.fst as it.extract it.toEnd and String.Iterator.snd as it.string.iter.extract it, and then use those two properties as before?

Bulhwi Cha (Mar 21 2023 at 01:01):

I'm not sure, but I assume it'll help only when you change the definition of String.Iterator back into the Mathlib3 one.

Bulhwi Cha (Mar 21 2023 at 01:18):

Richard Osborn said:

I had a quick look at Data.String.Basic, and it seems that Data.String.Defs was only partially ported. Is the plan to finish porting the missing definitions in that file?

I'll port data.string.defs before I push my commit to the port-data-string-basic-2 branch.

I first pushed my commits to the port-data-string-basic-2 branch, since porting data.string.defs would take more time than I expected.

Bulhwi Cha (Mar 27 2023 at 14:07):

I think !4#1054 is now ready to merge. :smile:

Jakob von Raumer (Mar 30 2023 at 11:21):

That's really cool! I felt bad about letting it sit for so long

Bulhwi Cha (Apr 05 2023 at 13:47):

instance : LinearOrder String where
  le_refl a := le_iff_toList_le.mpr le_rfl
  le_trans a b c := by
    simp only [le_iff_toList_le]
    apply le_trans
  lt_iff_le_not_le a b := by
    simp only [le_iff_toList_le, lt_iff_toList_lt, lt_iff_le_not_le]
  le_antisymm a b := by
    simp only [le_iff_toList_le,  toList_inj]
    apply le_antisymm
  le_total a b := by
    simp only [le_iff_toList_le]
    apply le_total
  decidable_le := String.decidableLE

The above code has the following error, which didn't occur before. Can anyone tell me how to solve this goal?

unsolved goals
case mk.mk
data✝¹ data: List Char
 compare { data := data✝¹ } { data := data } = compareOfLessAndEq { data := data✝¹ } { data := data }

GitHub PR discussion: https://github.com/leanprover-community/mathlib4/pull/1054#discussion_r1158533762

Ruben Van de Velde (Apr 05 2023 at 13:53):

Maybe related to !4#2858

Bulhwi Cha (Apr 05 2023 at 14:27):

Solution: add the line compare a b := compareOfLessAndEq a b to the instance declaration.

Notification Bot (Apr 05 2023 at 14:28):

Jeremy Tan has marked this topic as resolved.

Eric Wieser (Apr 07 2023 at 07:42):

That's the wrong solution

Eric Wieser (Apr 07 2023 at 07:42):

It discards the optimized string comparison function and replaces it with the naive one

Yaël Dillies (Apr 07 2023 at 08:46):

@Jeremy Tan, please don't resolve topics you're not involved in.

Yaël Dillies (Apr 07 2023 at 08:46):

Or simply don't resolve topics. It's noisy and broken.

Eric Wieser (Apr 07 2023 at 10:18):

(re "broken": if you resolve a topic, anyone who shared a link to that topic will find that the link they shared no longer works)

Notification Bot (Apr 07 2023 at 11:16):

Jeremy Tan has marked this topic as unresolved.

Bulhwi Cha (Apr 07 2023 at 14:29):

Eric Wieser said:

It discards the optimized string comparison function and replaces it with the naive one

Hmm, I'm not sure what I should do to solve the error correctly. Can you help me?

Eric Wieser (Apr 07 2023 at 14:48):

You need to provide a manual compare_eq field, I think

Eric Wieser (Apr 07 2023 at 14:48):

The error is coming from the default value for a proof field which no longer works; you need to provide that proof field explicitly, rather than replacing the data field with something that creates a diamond.

Eric Wieser (Apr 07 2023 at 14:49):

I'm afraid I don't know the name of the field; does the error message not tell you?

Bulhwi Cha (Apr 07 2023 at 15:01):

Eric Wieser said:

I'm afraid I don't know the name of the field; does the error message not tell you?

No, I don't think it does:

unsolved goals
case mk.mk
data✝¹ data: List Char
 compare { data := data✝¹ } { data := data } = compareOfLessAndEq { data := data✝¹ } { data := data }

Is the field you mentioned compare_eq_compareOfLessAndEq?

Ruben Van de Velde (Apr 07 2023 at 15:03):

instance : LinearOrder String where
  le_refl a := le_iff_toList_le.mpr le_rfl
  le_trans a b c := by
    simp only [le_iff_toList_le]
    apply le_trans
  lt_iff_le_not_le a b := by
    simp only [le_iff_toList_le, lt_iff_toList_lt, lt_iff_le_not_le]
  le_antisymm a b := by
    simp only [le_iff_toList_le,  toList_inj]
    apply le_antisymm
  le_total a b := by
    simp only [le_iff_toList_le]
    apply le_total
  decidable_le := String.decidableLE
  compare_eq_compareOfLessAndEq := sorry

Bulhwi Cha (Apr 07 2023 at 15:41):

Eric Wieser said:

The error is coming from the default value for a proof field which no longer works; you need to provide that proof field explicitly, rather than replacing the data field with something that creates a diamond.

Right now, I'm clueless about how to prove compare_eq_compareOfLessAndEq. I'll try it again later.

Ruben Van de Velde (Apr 07 2023 at 15:44):

I'm confused - the PR seems to be closed already?

Bulhwi Cha (Apr 07 2023 at 15:47):

Yes. :worried:

Bulhwi Cha (Apr 07 2023 at 16:47):

Eric Wieser said:

It discards the optimized string comparison function and replaces it with the naive one

Can you elaborate on "the optimized string comparison function"?

Bulhwi Cha (Apr 07 2023 at 16:49):

Here is my attempt to prove compare_eq_compareOfLessAndEq:

import Mathlib.Data.String.Basic

namespace String

instance : LinearOrder String where
  le_refl a := le_iff_toList_le.mpr le_rfl
  le_trans a b c := by
    simp only [le_iff_toList_le]
    apply le_trans
  lt_iff_le_not_le a b := by
    simp only [le_iff_toList_le, lt_iff_toList_lt, lt_iff_le_not_le]
  le_antisymm a b := by
    simp only [le_iff_toList_le,  toList_inj]
    apply le_antisymm
  le_total a b := by
    simp only [le_iff_toList_le]
    apply le_total
  decidable_le := String.decidableLE
  compare_eq_compareOfLessAndEq a b := by
    simp [compare, compareOfLessAndEq]
    split_ifs <;>
    rw [ lt_iff_toList_lt] at * <;>
    sorry

end String

Ruben Van de Velde (Apr 07 2023 at 16:52):

So where is the code that doesn't work? Or can you make a #mwe including imports?

Bulhwi Cha (Apr 07 2023 at 16:55):

I edited the above message.

Bulhwi Cha (Apr 07 2023 at 17:03):

Data.String.Basic has the instance String.LT', which overrides the default instance of LT String.

Bulhwi Cha (Apr 07 2023 at 17:12):

So, how do you close the following goal?

a b : String
h1: @LT.lt String instLTString a b
h2: ¬ @LT.lt String LT' a b
h3: ¬ a = b
 False

Bulhwi Cha (Apr 07 2023 at 17:17):

Bulhwi Cha said:

Solution: add the line compare a b := compareOfLessAndEq a b to the instance declaration.

I don't know. Perhaps my naive solution isn't wrong?

Eric Wieser (Apr 07 2023 at 18:02):

It is wrong, because there is already a docs4#instOrdString and your fix creates a second instance that is not defeq

Bulhwi Cha (Apr 07 2023 at 18:04):

"404 Not Found"

Eric Wieser (Apr 07 2023 at 18:04):

The sorry you're stuck on is proving that the instance you wanted to provide is defeq to the existing one. The proof is probably not completely trivial.

Eric Wieser (Apr 07 2023 at 18:06):

Although now I'm questioning whether it's actually not already defeq

Eric Wieser (Apr 07 2023 at 18:07):

Although now I'm questioning whether it's actually not already defeq

Eric Wieser (Apr 07 2023 at 18:07):

@thorimur can probably advise here, I'm not at lean so can't really help.

Bulhwi Cha (Apr 07 2023 at 18:12):

This might be relevant: https://github.com/leanprover-community/mathlib4/blob/a897757abcb0bffa1dc96f46017f1d65e0fd1f9b/Mathlib/Data/List/Lex.lean#L178-L181

It's 3:12 a.m. here in KR, so I'll get into bed now. :in_bed:

Eric Wieser (Apr 07 2023 at 18:22):

I don't think it's urgent to fix this

Eric Wieser (Apr 07 2023 at 18:23):

Feel free to open an issue, assign it to me/ thorimur, and abandon it entirely if you're not that interested in this.

Bulhwi Cha (Apr 08 2023 at 10:52):

import Mathlib.Data.String.Basic

open String

theorem List.lt_iff_lex_char_lt (l l' : List Char) : List.lt l l'  List.Lex Char.lt l l' := by
  constructor
  · intro h
    induction h with
    | nil b bs => exact Lex.nil
    | @head a as b bs hab => apply Lex.rel; assumption
    | @tail a as b bs hab hba _ ih =>
      have heq : a = b := _root_.le_antisymm (le_of_not_lt hba) (le_of_not_lt hab)
      subst b; apply Lex.cons; assumption
  · intro h
    induction h with
    | @nil a as => apply List.lt.nil
    | @cons a as bs _ ih => apply List.lt.tail <;> simp [ih]
    | @rel a as b bs h => apply List.lt.head; assumption

namespace String

instance : LinearOrder String where
  le_refl a := le_iff_toList_le.mpr le_rfl
  le_trans a b c := by
    simp only [le_iff_toList_le]
    apply le_trans
  lt_iff_le_not_le a b := by
    simp only [le_iff_toList_le, lt_iff_toList_lt, lt_iff_le_not_le]
  le_antisymm a b := by
    simp only [le_iff_toList_le,  toList_inj]
    apply le_antisymm
  le_total a b := by
    simp only [le_iff_toList_le]
    apply le_total
  decidable_le := String.decidableLE
  compare_eq_compareOfLessAndEq a b := by
    simp [compare, compareOfLessAndEq, toList, instLTString, List.instLTList, List.LT']
    split_ifs <;>
    simp [List.lt_iff_lex_char_lt] at * <;>
    contradiction

end String

Eric Wieser said:

The sorry you're stuck on is proving that the instance you wanted to provide is defeq to the existing one. The proof is probably not completely trivial.

It took me over an hour to prove compare_eq_compareOfLessAndEq. Thank you so much for your guidance!

Bulhwi Cha (Apr 08 2023 at 11:47):

GitHub PR: !4#3339

Alex J. Best (Apr 08 2023 at 15:32):

Eric Wieser said:

(re "broken": if you resolve a topic, anyone who shared a link to that topic will find that the link they shared no longer works)

Is that still true? I thought zulip fixed that long ago https://github.com/zulip/zulip/issues/19651. If not we should report it of course


Last updated: Dec 20 2023 at 11:08 UTC