Documentation

Mathlib.Control.ULiftable

Universe lifting for type families #

Some functors such as Option and List are universe polymorphic. Unlike type polymorphism where Option α is a function application and reasoning and generalizations that apply to functions can be used, Option.{u} and Option.{v} are not one function applied to two universe names but one polymorphic definition instantiated twice. This means that whatever works on Option.{u} is hard to transport over to Option.{v}. ULiftable is an attempt at improving the situation.

ULiftable Option.{u} Option.{v} gives us a generic and composable way to use Option.{u} in a context that requires Option.{v}. It is often used in tandem with ULift but the two are purposefully decoupled.

Main definitions #

Tags #

universe polymorphism functor

class ULiftable (f : outParam (Type uā‚€ → Type u₁)) (g : Type vā‚€ → Type v₁) :
Type (max (max (max (uā‚€ + 1) u₁) (vā‚€ + 1)) v₁)

Given a universe polymorphic type family M.{u} : Type u₁ → Type uā‚‚, this class convert between instantiations, from M.{u} : Type u₁ → Type uā‚‚ to M.{v} : Type v₁ → Type vā‚‚ and back.

f is an outParam, because g can almost always be inferred from the current monad. At any rate, the lift should be unique, as the intent is to only lift the same constants with different universe parameters.

Instances
    @[reducible, inline]
    abbrev ULiftable.symm (f : Type uā‚€ → Type u₁) (g : Type vā‚€ → Type v₁) [ULiftable f g] :

    Not an instance as it is incompatible with outParam. In practice it seems not to be needed anyway.

    Instances For
      @[implicit_reducible]
      instance ULiftable.refl (f : Type uā‚€ → Type u₁) [Functor f] [LawfulFunctor f] :
      @[reducible, inline]
      abbrev ULiftable.up {f : Type uā‚€ → Type u₁} {g : Type (max uā‚€ v) → Type v₁} [ULiftable f g] {α : Type uā‚€} :
      f α → g (ULift.{v, uā‚€} α)

      The most common practical use ULiftable (together with down), the function up.{v} takes x : M.{u} α and lifts it to M.{max u v} (ULift.{v} α)

      Instances For
        @[reducible, inline]
        abbrev ULiftable.down {f : Type uā‚€ → Type u₁} {g : Type (max uā‚€ v) → Type v₁} [ULiftable f g] {α : Type uā‚€} :
        g (ULift.{v, uā‚€} α) → f α

        The most common practical use of ULiftable (together with up), the function down.{v} takes x : M.{max u v} (ULift.{v} α) and lowers it to M.{u} α

        Instances For
          def ULiftable.adaptUp (F : Type vā‚€ → Type v₁) (G : Type (max vā‚€ uā‚€) → Type u₁) [ULiftable F G] [Monad G] {α : Type vā‚€} {β : Type (max vā‚€ uā‚€)} (x : F α) (f : α → G β) :
          G β

          convenient shortcut to avoid manipulating ULift

          Instances For
            def ULiftable.adaptDown {F : Type (max uā‚€ vā‚€) → Type u₁} {G : Type vā‚€ → Type v₁} [L : ULiftable G F] [Monad F] {α : Type (max uā‚€ vā‚€)} {β : Type vā‚€} (x : F α) (f : α → G β) :
            G β

            convenient shortcut to avoid manipulating ULift

            Instances For
              def ULiftable.upMap {F : Type uā‚€ → Type u₁} {G : Type (max uā‚€ vā‚€) → Type v₁} [ULiftable F G] [Functor G] {α : Type uā‚€} {β : Type (max uā‚€ vā‚€)} (f : α → β) (x : F α) :
              G β

              map function that moves up universes

              Instances For
                def ULiftable.downMap {F : Type (max uā‚€ vā‚€) → Type u₁} {G : Type uā‚€ → Type v₁} [ULiftable G F] [Functor F] {α : Type (max uā‚€ vā‚€)} {β : Type uā‚€} (f : α → β) (x : F α) :
                G β

                map function that moves down universes

                Instances For
                  @[reducible, inline]
                  abbrev ULiftable.up' {f : Type uā‚€ → Type u₁} {g : Type vā‚€ → Type v₁} [ULiftable f g] :
                  f PUnit.{uā‚€ + 1} → g PUnit.{vā‚€ + 1}

                  A version of up for a PUnit return type.

                  Instances For
                    @[reducible, inline]
                    abbrev ULiftable.down' {f : Type uā‚€ → Type u₁} {g : Type vā‚€ → Type v₁} [ULiftable f g] :
                    g PUnit.{vā‚€ + 1} → f PUnit.{uā‚€ + 1}

                    A version of down for a PUnit return type.

                    Instances For
                      theorem ULiftable.up_down {f : Type uā‚€ → Type u₁} {g : Type (max uā‚€ vā‚€) → Type v₁} [ULiftable f g] {α : Type uā‚€} (x : g (ULift.{vā‚€, uā‚€} α)) :
                      up (down x) = x
                      theorem ULiftable.down_up {f : Type uā‚€ → Type u₁} {g : Type (max uā‚€ vā‚€) → Type v₁} [ULiftable f g] {α : Type uā‚€} (x : f α) :
                      down (up x) = x
                      @[implicit_reducible]
                      instance instULiftableId :
                      ULiftable Id Id
                      @[implicit_reducible]
                      def StateT.uliftable' {s : Type uā‚€} {s' : Type u₁} {m : Type uā‚€ → Type vā‚€} {m' : Type u₁ → Type v₁} [ULiftable m m'] (F : s ā‰ƒ s') :
                      ULiftable (StateT s m) (StateT s' m')

                      for specific state types, this function helps to create a uliftable instance

                      Instances For
                        @[implicit_reducible]
                        instance instULiftableStateTULift {s : Type uā‚€} {m : Type uā‚€ → Type u_5} {m' : Type (max uā‚€ u_6) → Type u_7} [ULiftable m m'] :
                        ULiftable (StateT s m) (StateT (ULift.{u_6, uā‚€} s) m')
                        @[implicit_reducible]
                        instance StateT.instULiftableULiftULift {s : Type uā‚€} {m : Type (max uā‚€ vā‚€) → Type u_5} {m' : Type (max uā‚€ v₁) → Type u_6} [ULiftable m m'] :
                        ULiftable (StateT (ULift.{max vā‚€ uā‚€, uā‚€} s) m) (StateT (ULift.{max v₁ uā‚€, uā‚€} s) m')
                        @[implicit_reducible]
                        def ReaderT.uliftable' {s : Type uā‚€} {s' : Type u₁} {m : Type uā‚€ → Type u_5} {m' : Type u₁ → Type u_6} [ULiftable m m'] (F : s ā‰ƒ s') :
                        ULiftable (ReaderT s m) (ReaderT s' m')

                        for specific reader monads, this function helps to create a uliftable instance

                        Instances For
                          @[implicit_reducible]
                          instance instULiftableReaderTULift {s : Type uā‚€} {m : Type uā‚€ → Type u_5} {m' : Type (max uā‚€ u_6) → Type u_7} [ULiftable m m'] :
                          ULiftable (ReaderT s m) (ReaderT (ULift.{u_6, uā‚€} s) m')
                          @[implicit_reducible]
                          instance ReaderT.instULiftableULiftULift {s : Type uā‚€} {m : Type (max uā‚€ vā‚€) → Type u_5} {m' : Type (max uā‚€ v₁) → Type u_6} [ULiftable m m'] :
                          ULiftable (ReaderT (ULift.{max vā‚€ uā‚€, uā‚€} s) m) (ReaderT (ULift.{max v₁ uā‚€, uā‚€} s) m')
                          @[implicit_reducible]
                          def ContT.uliftable' {r : Type u_1} {r' : Type u_2} {m : Type u_1 → Type u_5} {m' : Type u_2 → Type u_6} [ULiftable m m'] (F : r ā‰ƒ r') :
                          ULiftable (ContT r m) (ContT r' m')

                          for specific continuation passing monads, this function helps to create a uliftable instance

                          Instances For
                            @[implicit_reducible]
                            instance instULiftableContTULift {s : Type u_5} {m : Type u_5 → Type u_6} {m' : Type (max u_5 u_7) → Type u_8} [ULiftable m m'] :
                            ULiftable (ContT s m) (ContT (ULift.{u_7, u_5} s) m')
                            @[implicit_reducible]
                            instance ContT.instULiftableULiftULift {s : Type uā‚€} {m : Type (max uā‚€ vā‚€) → Type u_5} {m' : Type (max uā‚€ v₁) → Type u_6} [ULiftable m m'] :
                            ULiftable (ContT (ULift.{max vā‚€ uā‚€, uā‚€} s) m) (ContT (ULift.{max v₁ uā‚€, uā‚€} s) m')
                            @[implicit_reducible]
                            def WriterT.uliftable' {w : Type u_3} {w' : Type u_4} {m : Type u_3 → Type u_5} {m' : Type u_4 → Type u_6} [ULiftable m m'] (F : w ā‰ƒ w') :
                            ULiftable (WriterT w m) (WriterT w' m')

                            for specific writer monads, this function helps to create a uliftable instance

                            Instances For
                              @[implicit_reducible]
                              instance instULiftableWriterTULift {s : Type uā‚€} {m : Type uā‚€ → Type u_5} {m' : Type (max uā‚€ u_6) → Type u_7} [ULiftable m m'] :
                              ULiftable (WriterT s m) (WriterT (ULift.{u_6, uā‚€} s) m')
                              @[implicit_reducible]
                              instance WriterT.instULiftableULiftULift {s : Type uā‚€} {m : Type (max uā‚€ vā‚€) → Type u_5} {m' : Type (max uā‚€ v₁) → Type u_6} [ULiftable m m'] :
                              ULiftable (WriterT (ULift.{max vā‚€ uā‚€, uā‚€} s) m) (WriterT (ULift.{max v₁ uā‚€, uā‚€} s) m')
                              @[implicit_reducible]
                              instance Except.instULiftable {ε : Type uā‚€} :
                              ULiftable (Except ε) (Except ε)
                              @[implicit_reducible]
                              instance Option.instULiftable :
                              ULiftable Option Option