Zulip Chat Archive

Stream: general

Topic: Monad Lifting


Mai (Jan 26 2026 at 00:27):

Why can't this automatically lift?

def foo : Option Nat := sorry
def bar : OptionT (StateM Nat) Nat := do
  let _ <- foo
  sorry

Jakub Nowak (Jan 26 2026 at 00:39):

Good question. There's ExceptT.instMonadLiftExcept but no lift for Option. Was it left on purpose or just was forgotten?

You can add it locally:

@[always_inline]
instance {m : Type u  Type v} [Monad m] : MonadLift Option (OptionT m) := fun e => OptionT.mk <| pure e

def foo : Option Nat := do return 2
def bar : OptionT (StateM Nat) Nat := do
  let _ <- foo
  sorry

Aaron Liu (Jan 26 2026 at 00:40):

there's also docs#liftOption

Mai (Jan 26 2026 at 00:45):

Also, StateM Nat Nat doesn't seem to lift to StateT Nat Option Nat. Shouldn't it?

Chris Henson (Jan 26 2026 at 01:09):

Some earlier discussion here: #lean4 > `MonadLift Option (OptionT m)`

Mai (Jan 26 2026 at 01:16):

Would something like this make sense?

instance [Pure m] : MonadLift (StateM σ) (StateT σ m) where
  monadLift m := pure  m

Mai (Jan 26 2026 at 01:17):

I am pretty sure Id lifts into any monad

Mai (Jan 26 2026 at 08:31):

Or even a more extreme generalization?

instance [MonadLift m n] : MonadLift (StateT σ m) (StateT σ n) where
  monadLift m σ := m σ

Mai (Jan 26 2026 at 08:32):

(The reasoning is that I would expect any automatic lifting in a do block to keep working after transforming the monad with StateT)

Mai (Jan 26 2026 at 09:34):

Oh no, Id isn't MonadLift, it's MonadLiftT... :cry:
Would this make sense?

instance [MonadLiftT m n] : MonadLiftT (StateT σ m) (StateT σ n) where
  monadLift m σ := m σ

Last updated: Feb 28 2026 at 14:05 UTC