Zulip Chat Archive

Stream: Is there code for X?

Topic: monad question


Floris van Doorn (Sep 20 2020 at 04:34):

@[simp] lemma map_map_seq {α β γ δ} (m : Type*  Type*) [monad m] [is_lawful_monad m]
  (f : α  β  γ) (g : γ  δ) (u : m α) (v : m β) :
  g <$> (f <$> u <*> v) = (λ x y, g (f x y)) <$> u <*> v :=
sorry

Is this true? I want it for filters.

Mario Carneiro (Sep 20 2020 at 04:39):

@[simp] lemma map_map_seq {α β γ δ} (m : Type*  Type*) [monad m] [is_lawful_monad m]
  (f : α  β  γ) (g : γ  δ) (u : m α) (v : m β) :
  g <$> (f <$> u <*> v) = (λ x y, g (f x y)) <$> u <*> v :=
by simp [ bind_map_eq_seq, bind_assoc,  bind_pure_comp_eq_map]

Floris van Doorn (Sep 20 2020 at 05:06):

Thanks!

Simon Hudon (Sep 20 2020 at 05:07):

Have you tried using simp with norm_monad. That might do it completely automatically

Simon Hudon (Sep 20 2020 at 05:07):

Actually norm_functor might be enough

Floris van Doorn (Sep 20 2020 at 05:18):

Oh nice, that also works:

@[simp] lemma map_map_seq {α β γ δ} (m : Type*  Type*) [monad m] [is_lawful_monad m]
  (f : α  β  γ) (g : γ  δ) (u : m α) (v : m β) :
  g <$> (f <$> u <*> v) = (λ x y, g (f x y)) <$> u <*> v :=
by simp with functor_norm

However, instantiating to filters doesn't work:

@[simp] lemma {u} filter.map_map_seq {α β γ δ : Type u} (f : α  β  γ) (g : γ  δ) (u : filter α)
  (v : filter β) : map g (map f u <*> v) = map (λ x y, g (f x y)) u <*> v :=
by { convert @map_map_seq _ _ _ _ filter filter.monad filter.is_lawful_monad f g u v,
 -- Goal: ⊢ filter.has_seq = applicative.to_has_seq
}

So clearly I'm doing something I'm not supposed to do...

I might be multiple levels deep into #xy. My previous goal was the following lemma, where after the following partial proof I wanted to rewrite with the aforementioned lemma.

import topology.list topology.algebra.monoid

open filter

@[simp] lemma tendsto_pure_left {α β} (f : α  β) (x : α) (u : filter β) :
  tendsto f (pure x) u   s  u, f x  s :=
by { simp [tendsto, pure_le_iff] }

lemma continuous_prod {α} [topological_space α] [monoid α] [has_continuous_mul α] :
  continuous (list.prod : list α  α) :=
begin
  rw [continuous_iff_continuous_at], intros l, simp [continuous_at],
  cases l, { simp [nhds_nil, mem_of_nhds] {contextual := tt} },
  simp [nhds_cons, tendsto],
end

Simon Hudon (Sep 20 2020 at 05:22):

Your lemma only needs applicative m and is_lawful_applicative m as an assumption. When you change that, your monad will no longer be converted into an applicative in the general lemma

Floris van Doorn (Sep 20 2020 at 05:26):

I see, that works. Thanks!
It still seems to be a design flaw that filter has multiple transitive has_seq instances. Or is that inevitable?

Simon Hudon (Sep 20 2020 at 05:29):

No, that seems like a mistake. In filter/basic.lean, line 1452:

instance : applicative filter := { map := @filter.map, seq := @filter.seq }

What happens if you delete that line?

Simon Hudon (Sep 20 2020 at 05:30):

Having a separate monad and applicative instance is useful for monad transformers because you have different assumptions for each:

instance [applicative m] : applicative (foo_t m) := ...
instance [monad m] : monad (foo_t m) := ...

But that does not apply for filter

Floris van Doorn (Sep 20 2020 at 05:32):

A couple of things break later on (not too many). It seems to be done intentionally, since line 1438 says:

-- this section needs to be before applicative, otherwise the wrong instance will be chosen

Simon Hudon (Sep 20 2020 at 05:32):

Actually, here's the answer:

https://github.com/leanprover-community/mathlib/blob/master/src/order/filter/basic.lean#L1387-L1393

Floris van Doorn (Sep 20 2020 at 05:33):

Ah ok

Simon Hudon (Sep 20 2020 at 05:34):

The applicative and monad definitions are distinct, that's why you have to pick the right one in the lemma that you were proving in this thread


Last updated: Dec 20 2023 at 11:08 UTC