Zulip Chat Archive

Stream: new members

Topic: Universe issues with polymorphic types


Calvin Lee (Jan 22 2021 at 19:44):

Hello! I'm having a bit of some trouble with universes and polymorphism
I would like to have a continuation-based type with a polymorphic answer type. In particular I am implementing the "LogicT" monad transformer, which uses this. My current formulation from the Logic paper, using success and failure continuations is as follows:

def FK (ans : Type u) : Type u := ans
def SK (ans : Type u) (a : Type u) : Type u := a -> FK ans -> ans

def LogicT (m : Type u -> Type u) (a : Type u) : Type (u + 1) :=
  {ans : Type u} -> SK (m ans) a -> FK (m ans) -> m ans

Unfortunately due to the polymorphism, I have to raise the universe level at the very end. This is fine, but it starts to create issues when I have to do things like LogicT m X where X contains some other instance of a LogicT m a
Is there any way to get around this or am I going down the wrong path?

Yakov Pechersky (Jan 22 2021 at 20:06):

Would this work?

universes u v

def FK (ans : Type*) : Type* := ans
def SK (ans : Type*) (a : Type*) : Type* := a -> FK ans -> ans

def LogicT (m : Type u -> Type v) (a : Type u) {ans : Type u} : Type (max u v) :=
  SK (m ans) a -> FK (m ans) -> m ans

Yakov Pechersky (Jan 22 2021 at 20:07):

It can be generalized to more universes it seems:

def FK (ans : Type*) : Type* := ans
def SK (ans : Type*) (a : Type*) : Type* := a -> FK ans -> ans

def LogicT (m : Type* -> Type*) (a : Type*) {ans : Type*} : Type* :=
  SK (m ans) a -> FK (m ans) -> m ans

#check LogicT

Calvin Lee (Jan 22 2021 at 20:27):

What is Type*? It doesn't seem to work for me, probably because I'm using lean4.

But the issue with putting {ans : Type u} in the definition is that I can no longer instantiate classes for it
For example I have this definition

instance [Monad m] : Monad (LogicT m) := ...

Which if I add ans as an optional argument complains

application type mismatch
  Monad (LogicT m)
argument
  LogicT m
has type
  Type ?u.247  {ans : Type ?u.247}  Type (max ?u.247 ?u.246)
but is expected to have type
  Type ?u.252  Type ?u.251

Yakov Pechersky (Jan 22 2021 at 20:32):

Use Type _ instead: https://leanprover.github.io/lean4/doc/typeobjs.html?highlight=type*

Yakov Pechersky (Jan 22 2021 at 20:35):

def FK (ans : Type _) : Type _ := ans
def SK (ans : Type _) (a : Type _) : Type _ := a -> FK ans -> ans

def LogicT (m : Type _ -> Type _) (a : Type _) : Type _ :=
  Π {ans : Type _}, SK (m ans) a -> FK (m ans) -> m ans

#check LogicT

Yes you get the increase in universes unfortunately.

Calvin Lee (Jan 22 2021 at 20:35):

Hm, is there any way to nest them then? Possibly with a function that increases the universe by a level?

Yakov Pechersky (Jan 22 2021 at 20:36):

def FK (ans : Type _) : Type _ := ans
def SK (ans : Type _) (a : Type _) : Type _ := a -> FK ans -> ans

def LogicT (m : Type _ -> Type _) (a : Type _) : Type _ :=
  Π {ans : Type _}, SK (m ans) a -> FK (m ans) -> m ans

instance {m} [monad m] : monad (LogicT m) :=
{ map := _,
  map_const := _,
  pure := _,
  seq := _,
  seq_left := _,
  seq_right := _,
  bind := _ }

Yakov Pechersky (Jan 22 2021 at 20:37):

Can you fill those in Lean 3?

Calvin Lee (Jan 22 2021 at 20:51):

I just did pure & bind, since that seems to compile just fine

def FK (ans : Type*) : Type* := ans
def SK (ans : Type*) (a : Type*) : Type* := a -> FK ans -> ans

def LogicT (m : Type* -> Type*) (a : Type*) : Type* :=
  Π {ans : Type*}, SK (m ans) a -> FK (m ans) -> m ans

def logicPure {m a} [monad m] (x : a) : LogicT m a := fun _ sk fk, sk x fk
def logicBind {m a b} [monad m] (x : LogicT m a)  (f : a -> LogicT m b) : LogicT m b :=
  λ _ sk,  x (λ  a, (f a) sk)

instance {m} [monad m] : monad (LogicT m) :=
{ pure := λ _ , logicPure,
  bind := λ _ _, logicBind,
}

Yakov Pechersky (Jan 22 2021 at 20:53):

Great, so will that work in Lean 4?

Calvin Lee (Jan 22 2021 at 21:06):

Yes! the bindings for monads and such work great. The issue is this (arguably important) function from the paper

def msplit {m a} (x : LogicT m a) : LogicT m (Maybe (a , LogicT m a)) := _

which is used to create "fairness" results and reading of one result at a time even with a strict monad m

Yakov Pechersky (Jan 22 2021 at 21:08):

Option is Lean4 for Maybe, but I'm sure you know that

Calvin Lee (Jan 22 2021 at 21:08):

Oh that's helpful, I thought there wasn't a Maybe so I created it myself....


Last updated: Dec 20 2023 at 11:08 UTC