Zulip Chat Archive
Stream: lean4
Topic: IO with a type parameter in universe > 1
Juan Pablo Romero (Jul 12 2022 at 15:13):
Hi, I'm trying to create the following type:
universe u
inductive Wrapper : Type u -> Type (u + 1) where
| Pure {A : Type u} (value: A) : Wrapper A
| Effect {A : Type u} (io: IO A) : Wrapper A
which fails because IO
has type Type → Type
.
Is there a way to overcome this issue?
Mauricio Collares (Jul 12 2022 at 15:18):
Relevant: https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/universe.20polymorphic.20IO
Sébastien Michelland (Jul 12 2022 at 15:25):
Which I should be able to look into again. I left it unfinished because of more pressing problems.
Juan Pablo Romero (Jul 12 2022 at 19:41):
I managed to make it work with liberal use of ULift
universe u
inductive Wrapper : Type u -> Type (u + 1) where
| Pure {A : Type u} (value: A) : Wrapper A
| Effect {A : Type} (io: ULift.{u} (IO A)) : Wrapper (ULift.{u} A)
def run {A: Type u} {B: Type} (w: Wrapper A) (next: A -> IO B) : IO B :=
match w with
| .Pure a =>
next a
| .Effect lio =>
let io := ULift.down.{u} lio
io.bind <| fun a => next (ULift.up.{u} a)
Sébastien Michelland (Jul 12 2022 at 19:54):
Right. If this is sufficient for your needs, then it's likely the best option. Note that compared to your original definition you are limited to computing in Type
while in the IO monad. I might be wrong here, but this looks like a free(r) monad, and I believe this typing will make it hard for you to bind with effects. You can see how already your continuation is restricted to B: Type
. If you want to use a B: Type v
or simply a Wrapper B
to continue the program, you will find yourself matching B
against a universe lift of A: Type
in the Effect
constructor, so basically you're grounded at Type 0.
Juan Pablo Romero (Jul 12 2022 at 21:21):
It's good for now, thanks!
Last updated: Dec 20 2023 at 11:08 UTC