diff --git a/theories/fin_maps.v b/theories/fin_maps.v
index 4a47d246ef80a9e9c8509440bb5cc420016cdb92..5a3b8df1ddd52e64268999b73c20328e247cac4c 100644
--- a/theories/fin_maps.v
+++ b/theories/fin_maps.v
@@ -104,6 +104,12 @@ index contains a value in the second map as well. *)
 Instance map_difference `{Merge M} {A} : Difference (M A) :=
   difference_with (λ _ _, None).
 
+(** A stronger variant of map that allows the mapped function to use the index
+of the elements. Implemented by conversion to lists, so not very efficient. *)
+Definition map_imap `{∀ A, Insert K A (M A), ∀ A, Empty (M A),
+    ∀ A, FinMapToList K A (M A)} {A B} (f : K → A → option B) (m : M A) : M B :=
+  map_of_list (omap (λ ix, (fst ix,) <$> curry f ix) (map_to_list m)).
+
 (** * Theorems *)
 Section theorems.
 Context `{FinMap K M}.
@@ -585,6 +591,23 @@ Proof.
   exists i x. rewrite <-elem_of_map_to_list, Hm. by left.
 Qed.
 
+(** Properties of the imap function *)
+Lemma lookup_imap {A B} (f : K → A → option B) m i :
+  map_imap f m !! i = m !! i ≫= f i.
+Proof.
+  unfold map_imap; destruct (m !! i ≫= f i) as [y|] eqn:Hi; simpl.
+  * destruct (m !! i) as [x|] eqn:?; simplify_equality'.
+    apply elem_of_map_of_list_1_help.
+    { apply elem_of_list_omap; exists (i,x); split;
+        [by apply elem_of_map_to_list|by simplify_option_equality]. }
+    intros y'; rewrite elem_of_list_omap; intros ([i' x']&Hi'&?).
+    by rewrite elem_of_map_to_list in Hi'; simplify_option_equality.
+  * apply not_elem_of_map_of_list; rewrite elem_of_list_fmap.
+    intros ([i' x]&->&Hi'); simplify_equality'.
+    rewrite elem_of_list_omap in Hi'; destruct Hi' as ([j y]&Hj&?).
+    rewrite elem_of_map_to_list in Hj; simplify_option_equality.
+Qed.
+
 (** ** Properties of conversion from collections *)
 Lemma lookup_map_of_collection {A} `{FinCollection K C}
     (f : K → option A) X i x :