Zulip Chat Archive
Stream: lean4
Topic: how to implement toProxy? (universe polymorphism problem)
Serhii Khoma (srghma) (Jul 29 2025 at 07:48):
I am trying to implement https://github.com/jwiegley/coq-pipes/blob/ec4e7884dc2d2c1a55ee075103c964b4f65c7be6/src/Pipes/Extras.v#L27
inductive Proxy.{u} (a' a b' b : Type u) (m : Type u → Type u) (r : Type u) : Type (u+1)
| Request : a' → (a → Proxy a' a b' b m r) → Proxy a' a b' b m r
| Respond : b → (b' → Proxy a' a b' b m r) → Proxy a' a b' b m r
| M {x : Type u} (op : m x) (cont : x → Proxy a' a b' b m r) : Proxy a' a b' b m r
| Pure : r → Proxy a' a b' b m r
abbrev CProxy (a' a b' b : Type u) (m : Type u → Type u) (r : Type u) : Type (u+1) :=
∀ (s : Type u),
(a' → (a → s) → s) → -- Handle Request
(b → (b' → s) → s) → -- Handle Respond
(∀ x, (x → s) → m x → s) → -- Handle
(r → s) → -- Handle Pure
s
-- Convert inductive Proxy into Church-encoded CProxy
def fromProxy (p : Proxy a' a b' b m r) : CProxy a' a b' b m r :=
match p with
/- | .Request xa' k => CProxy.Request xa' (fun a => fromProxy (k a)) -/
/- | .Respond xb k => CProxy.Respond xb (fun b' => fromProxy (k b')) -/
| .Request xa' k => fun s ka kb km kp => ka xa' (fun xa => fromProxy (k xa) s ka kb km kp)
| .Respond xb k => fun s ka kb km kp => kb xb (fun b' => fromProxy (k b') s ka kb km kp)
| .M mx k => fun s ka kb km kp => km _ (fun x => fromProxy (k x) s ka kb km kp) mx
| .Pure xr => fun _s _ka _kb _km kp => kp xr
def toProxy (p : CProxy.{u} a' a b' b m r) : Proxy.{u} a' a b' b m r :=
p (Proxy a' a b' b m r)
(fun a' k => Proxy.Request a' (fun a => toProxy (k a)))
(fun b k => Proxy.Respond b (fun b' => toProxy (k b')))
(fun _ k mx => Proxy.M mx (fun x => toProxy (k x)))
Proxy.Pure
but the toProxy throws error
Application type mismatch: In the application
p (Proxy a' a b' b m r)
the argument
Proxy a' a b' b m r
has type
Type (u + 1) : Type (u + 2)
but is expected to have type
Type u : Type (u + 1)
I'm stuck and dont know how to go from here
I've heard there is a universe bump problem with Church-encoding. Probably that's it. How to overcome it?
Quang Dao (Jul 30 2025 at 11:49):
Try changing universe level of CProxy to u + 1 for p?
Serhii Khoma (srghma) (Jul 30 2025 at 12:56):
Quang Dao said:
Try changing universe level of
CProxytou + 1forp?
like this ? this works
inductive Proxy.{u} (r : Type u) : Type (u+1)
| Pure : r → Proxy r
abbrev CProxy.{u} (r : Type u) : Type (u+2) :=
∀ {s : Type (u+1)},
(r → s) → -- Handle Pure
s
-- Convert inductive Proxy into Church-encoded CProxy
def fromProxy (p : Proxy r) : CProxy r :=
match p with
| .Pure xr => fun kp => kp xr
def toProxy (p : CProxy.{u} r) : Proxy.{u} r :=
p Proxy.Pure
this works too
inductive Proxy.{u} (r : Type u) : Type (u+1)
| Pure : r → Proxy r
abbrev CProxy.{u} (r : Type u) : Type (u+2) :=
∀ (s : Type (u+1)),
(r → s) → -- Handle Pure
s
-- Convert inductive Proxy into Church-encoded CProxy
def fromProxy (p : Proxy r) : CProxy r :=
match p with
| .Pure xr => fun _s kp => kp xr
def toProxy (p : CProxy.{u} r) : Proxy.{u} r :=
p (Proxy.{u} r) Proxy.Pure
this works too
inductive Proxy.{u} (a' a b' b : Type u) (m : Type u → Type u) (r : Type u) : Type (u+1)
| Request : a' → (a → Proxy a' a b' b m r) → Proxy a' a b' b m r
| Respond : b → (b' → Proxy a' a b' b m r) → Proxy a' a b' b m r
| M {x : Type u} (op : m x) (cont : x → Proxy a' a b' b m r) : Proxy a' a b' b m r
| Pure : r → Proxy a' a b' b m r
abbrev CProxy.{u} (a' a b' b : Type u) (m : Type u → Type u) (r : Type u) : Type (u+2) :=
∀ (s : Type (u+1)),
(a' → (a → s) → s) → -- Handle Request
(b → (b' → s) → s) → -- Handle Respond
(∀ x, (x → s) → m x → s) → -- Handle
(r → s) → -- Handle Pure
s
-- Convert inductive Proxy into Church-encoded CProxy
def fromProxy (p : Proxy a' a b' b m r) : CProxy a' a b' b m r :=
match p with
/- | .Request xa' k => CProxy.Request xa' (fun a => fromProxy (k a)) -/
/- | .Respond xb k => CProxy.Respond xb (fun b' => fromProxy (k b')) -/
| .Request xa' k => fun s ka kb km kp => ka xa' (fun xa => fromProxy (k xa) s ka kb km kp)
| .Respond xb k => fun s ka kb km kp => kb xb (fun b' => fromProxy (k b') s ka kb km kp)
| .M mx k => fun s ka kb km kp => km _ (fun x => fromProxy (k x) s ka kb km kp) mx
| .Pure xr => fun _s _ka _kb _km kp => kp xr
def toProxy (p : CProxy.{u} a' a b' b m r) : Proxy.{u} a' a b' b m r :=
p (Proxy a' a b' b m r)
(fun xa' xk => Proxy.Request xa' xk)
(fun xb xk => Proxy.Respond xb xk)
(fun _ xk mx => Proxy.M mx xk)
Proxy.Pure
-- but it broke
abbrev CProxy.runEffect {m : Type u → Type u} {a b' r : Type u} [Monad m] (eff : CProxy.{u} PEmpty a b' PEmpty m r) : m r :=
eff (m r)
(fun x _ => PEmpty.elim x) -- Handle Request (impossible)
(fun x _ => PEmpty.elim x) -- Handle Respond (impossible)
(fun _ f mt => mt >>= f) -- Handle M
pure -- Handle Pure
worked with this definition https://github.com/sergeynordicresults/lean-pipes/blob/b4f9dc7f7ae49dac0eb026566f7055dbac89426e/pipes/Pipes/Extra/ChurchPipes/Internal.lean#L2
what's left is to prove this theorem https://github.com/sergeynordicresults/lean-pipes/blob/b4f9dc7f7ae49dac0eb026566f7055dbac89426e/pipes/Pipes/Extra/ChurchPipes/FromTo.lean#L62 but even coq version uses axioms, so wont do it now
tnx
Last updated: Dec 20 2025 at 21:32 UTC