diff --git a/src/Init/Data/String/Iter.lean b/src/Init/Data/String/Iter.lean index 79d4215ef8..4e967b0327 100644 --- a/src/Init/Data/String/Iter.lean +++ b/src/Init/Data/String/Iter.lean @@ -6,29 +6,5 @@ Authors: Markus Himmel module prelude -public import Init.Data.Iterators.Combinators.FilterMap -public import Init.Data.Iterators.Consumers.Collect - -set_option doc.verso true - -namespace Std - -/-- -Convenience function for turning an iterator into a list of strings, provided the output of the -iterator implements {name}`ToString`. --/ -@[inline] -public abbrev Iter.toStringList {α β : Type} [Iterator α Id β] [ToString β] - (it : Iter (α := α) β) : List String := - it.map toString |>.toList - -/-- -Convenience function for turning an iterator into an array of strings, provided the output of the -iterator implements {name}`ToString`. --/ -@[inline] -public abbrev Iter.toStringArray {α β : Type} [Iterator α Id β] [ToString β] - (it : Iter (α := α) β) : Array String := - it.map toString |>.toArray - -end Std +public import Init.Data.String.Iter.Basic +public import Init.Data.String.Iter.Intercalate diff --git a/src/Init/Data/String/Iter/Basic.lean b/src/Init/Data/String/Iter/Basic.lean new file mode 100644 index 0000000000..79d4215ef8 --- /dev/null +++ b/src/Init/Data/String/Iter/Basic.lean @@ -0,0 +1,34 @@ +/- +Copyright (c) 2026 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Markus Himmel +-/ +module + +prelude +public import Init.Data.Iterators.Combinators.FilterMap +public import Init.Data.Iterators.Consumers.Collect + +set_option doc.verso true + +namespace Std + +/-- +Convenience function for turning an iterator into a list of strings, provided the output of the +iterator implements {name}`ToString`. +-/ +@[inline] +public abbrev Iter.toStringList {α β : Type} [Iterator α Id β] [ToString β] + (it : Iter (α := α) β) : List String := + it.map toString |>.toList + +/-- +Convenience function for turning an iterator into an array of strings, provided the output of the +iterator implements {name}`ToString`. +-/ +@[inline] +public abbrev Iter.toStringArray {α β : Type} [Iterator α Id β] [ToString β] + (it : Iter (α := α) β) : Array String := + it.map toString |>.toArray + +end Std diff --git a/src/Init/Data/String/Iter/Intercalate.lean b/src/Init/Data/String/Iter/Intercalate.lean new file mode 100644 index 0000000000..414a5da70e --- /dev/null +++ b/src/Init/Data/String/Iter/Intercalate.lean @@ -0,0 +1,36 @@ +/- +Copyright (c) 2026 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Julia Markus Himmel +-/ +module + +prelude +public import Init.Data.Iterators.Combinators.Monadic.FilterMap +public import Init.Data.String.Basic +import Init.Data.String.Slice + +set_option doc.verso true + +namespace Std + +/-- +Appends all the elements in the iterator, in order. +-/ +public def Iter.joinString {α β : Type} [Iterator α Id β] [IteratorLoop α Id Id] [ToString β] + (it : Std.Iter (α := α) β) : String := + (it.map toString).fold (init := "") (· ++ ·) + +/-- +Appends the elements of the iterator into a string, placing the separator {name}`s` between them. +-/ +@[inline] +public def Iter.intercalateString {α β : Type} [Iterator α Id β] [IteratorLoop α Id Id] [ToString β] + (s : String.Slice) (it : Std.Iter (α := α) β) : String := + it.map toString + |>.fold (init := none) (fun + | none, sl => some sl + | some str, sl => some (str ++ s ++ sl)) + |>.getD "" + +end Std diff --git a/src/Init/Data/String/Lemmas.lean b/src/Init/Data/String/Lemmas.lean index 3918ce6a6c..59783b8adf 100644 --- a/src/Init/Data/String/Lemmas.lean +++ b/src/Init/Data/String/Lemmas.lean @@ -17,6 +17,7 @@ public import Init.Data.String.Lemmas.Pattern public import Init.Data.String.Lemmas.Slice public import Init.Data.String.Lemmas.Iterate public import Init.Data.String.Lemmas.Intercalate +public import Init.Data.String.Lemmas.Iter import Init.Data.Order.Lemmas public import Init.Data.String.Basic import Init.Data.Char.Lemmas diff --git a/src/Init/Data/String/Lemmas/Intercalate.lean b/src/Init/Data/String/Lemmas/Intercalate.lean index 6ccc83bb81..f8a2fc90c0 100644 --- a/src/Init/Data/String/Lemmas/Intercalate.lean +++ b/src/Init/Data/String/Lemmas/Intercalate.lean @@ -10,6 +10,7 @@ public import Init.Data.String.Defs import all Init.Data.String.Defs public import Init.Data.String.Slice import all Init.Data.String.Slice +import Init.ByCases public section @@ -42,6 +43,16 @@ theorem intercalate_cons_of_ne_nil {s t : String} {l : List String} (h : l ≠ [ match l, h with | u::l, _ => by simp +theorem intercalate_append_of_ne_nil {l m : List String} {s : String} (hl : l ≠ []) (hm : m ≠ []) : + s.intercalate (l ++ m) = s.intercalate l ++ s ++ s.intercalate m := by + induction l with + | nil => simp_all + | cons hd tl ih => + rw [List.cons_append, intercalate_cons_of_ne_nil (by simp_all)] + by_cases ht : tl = [] + · simp_all + · simp [ih ht, intercalate_cons_of_ne_nil ht, String.append_assoc] + @[simp] theorem toList_intercalate {s : String} {l : List String} : (s.intercalate l).toList = s.toList.intercalate (l.map String.toList) := by diff --git a/src/Init/Data/String/Lemmas/Iter.lean b/src/Init/Data/String/Lemmas/Iter.lean new file mode 100644 index 0000000000..34c659f770 --- /dev/null +++ b/src/Init/Data/String/Lemmas/Iter.lean @@ -0,0 +1,51 @@ +/- +Copyright (c) 2026 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Julia Markus Himmel +-/ +module + +prelude +public import Init.Data.String.Iter.Intercalate +public import Init.Data.String.Slice +import all Init.Data.String.Iter.Intercalate +import all Init.Data.String.Defs +import Init.Data.String.Lemmas.Intercalate +import Init.Data.Iterators.Lemmas.Consumers.Loop +import Init.Data.Iterators.Lemmas.Combinators.FilterMap + +namespace Std.Iter + +@[simp] +public theorem joinString_eq {α β : Type} [Std.Iterator α Id β] [Std.Iterators.Finite α Id] + [Std.IteratorLoop α Id Id] [Std.LawfulIteratorLoop α Id Id] [ToString β] + {it : Std.Iter (α := α) β} : it.joinString = String.join (it.toList.map toString) := by + rw [joinString, String.join, ← foldl_toList, toList_map] + +@[simp] +public theorem intercalateString_eq {α β : Type} [Std.Iterator α Id β] [Std.Iterators.Finite α Id] + [Std.IteratorLoop α Id Id] [Std.LawfulIteratorLoop α Id Id] [ToString β] {s : String.Slice} + {it : Std.Iter (α := α) β} : + it.intercalateString s = s.copy.intercalate (it.toList.map toString) := by + simp only [intercalateString, String.appendSlice_eq, ← foldl_toList, toList_map] + generalize s.copy = s + suffices ∀ (l m : List String), + (l.foldl (init := if m = [] then none else some (s.intercalate m)) + (fun | none, sl => some sl | some str, sl => some (str ++ s ++ sl))).getD "" + = s.intercalate (m ++ l) by + simpa [-foldl_toList] using this (it.toList.map toString) [] + intro l m + induction l generalizing m with + | nil => cases m <;> simp + | cons hd tl ih => + rw [List.append_cons, ← ih, List.foldl_cons] + congr + simp only [List.append_eq_nil_iff, List.cons_ne_self, and_false, ↓reduceIte] + match m with + | [] => simp + | x::xs => + simp only [reduceCtorEq, ↓reduceIte, List.cons_append, Option.some.injEq] + rw [← List.cons_append, String.intercalate_append_of_ne_nil (by simp) (by simp), + String.intercalate_singleton] + +end Std.Iter diff --git a/src/Init/Data/String/Slice.lean b/src/Init/Data/String/Slice.lean index 087f5f765f..1048ae1121 100644 --- a/src/Init/Data/String/Slice.lean +++ b/src/Init/Data/String/Slice.lean @@ -11,7 +11,7 @@ public import Init.Data.Ord.Basic public import Init.Data.Iterators.Combinators.FilterMap public import Init.Data.String.ToSlice public import Init.Data.String.Subslice -public import Init.Data.String.Iter +public import Init.Data.String.Iter.Basic public import Init.Data.String.Iterate import Init.Data.Iterators.Consumers.Collect import Init.Data.Iterators.Consumers.Loop