Zulip Chat Archive
Stream: lean4
Topic: List.map_map How to use optimization
lean_user (Jun 16 2025 at 01:13):
import Lean
#check List.map_map
-- List.map_map.{u_1, u_2, u_3} {β : Type u_1} {γ : Type u_2} {α : Type u_3} {g : β → γ} {f : α → β} {l : List α} :
-- List.map g (List.map f l) = List.map (g ∘ f) l
set_option trace.compiler.ir.result true in
@[simp] def test (l : List Nat) (g : Nat → Nat) (f : Nat → Nat)
: List Nat :=
List.map g (List.map f l)
--[result]
--def test (x_1 : obj) (x_2 : obj) (x_3 : obj) : obj :=
-- let x_4 : obj := ctor_0[List.nil];
-- let x_5 : obj := List.mapTR.loop._rarg x_3 x_1 x_4;
-- let x_6 : obj := List.mapTR.loop._rarg x_2 x_5 x_4;
-- ret x_
@[simp] theorem test_optimized_eq (l : List Nat) (g f : Nat → Nat) :
test l g f = List.map (g ∘ f) l := by
simp [List.map_map]
#eval do
Lean.Compiler.compile #[``test]
Lean.Compiler.LCNF.showDecl .base ``test
--def test l g f : List Nat :=
-- let _x.1 := @List.mapTR _ _ f l;
-- let _x.2 := @List.mapTR _ _ g _x.1;
-- return _x.2
Aaron Liu (Jun 16 2025 at 01:17):
Can you provide a #mwe?
Robin Arnez (Jun 16 2025 at 08:48):
This is currently not supported
Markus Himmel (Jun 16 2025 at 08:57):
If you use iterators on the latest nightly, the two maps are fused, though you get an additional loop turning the array that is used internally back into a list. If you use arrays instead of lists, there will only be a single loop.
import Std.Data.Iterators
set_option trace.compiler.ir.result true in
def test (l : List Nat) (g : Nat → Nat) (f : Nat → Nat) : List Nat :=
((l.iter.map f).map g).toList
/-
def Std.Iterators.IterM.DefaultConsumers.toArrayMapped.go._at.test._spec_2 (x_1 : obj) (x_2 : obj) (x_3 : obj) (x_4 : obj) : obj :=
case x_3 : obj of
List.nil →
dec x_2;
dec x_1;
ret x_4
List.cons →
let x_5 : obj := proj[0] x_3;
inc x_5;
let x_6 : obj := proj[1] x_3;
inc x_6;
dec x_3;
inc x_2;
let x_7 : obj := app x_2 x_5;
inc x_1;
let x_8 : obj := app x_1 x_7;
let x_9 : obj := Array.push ◾ x_4 x_8;
let x_10 : obj := Std.Iterators.IterM.DefaultConsumers.toArrayMapped.go._at.test._spec_2 x_1 x_2 x_6 x_9;
ret x_10
def test._closed_1 : obj :=
let x_1 : obj := ctor_0[List.nil];
let x_2 : obj := Array.mk ◾ x_1;
ret x_2
def test (x_1 : obj) (x_2 : obj) (x_3 : obj) : obj :=
let x_4 : obj := test._closed_1;
let x_5 : obj := Std.Iterators.IterM.DefaultConsumers.toArrayMapped.go._at.test._spec_2 x_2 x_3 x_1 x_4;
let x_6 : obj := Array.toList ◾ x_5;
ret x_6
-/
Last updated: Dec 20 2025 at 21:32 UTC