Imports
/- Copyright (c) 2026 Terence Rokop. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Terence Rokop -/ module public import Mathlib.CategoryTheory.Comma.Arrow public import Mathlib.CategoryTheory.FiberedCategory.Fiber public import Mathlib.CategoryTheory.FiberedCategory.Fibered public import Mathlib.CategoryTheory.FiberedCategory.HomLift public import Mathlib.Tactic.Attr.Core

Discrete fibrations: lifting data

A functor p : C ⥤ B is a discrete fibration when every g : b ⟶ p.obj c has a unique lift with codomain c ([LoregianRiehl2018] § 2.1; [nLabDiscreteFibration]). This module carries that lifting data as a structure and relates it to mathlib's fibred-category API.

Main definitions

    DiscreteFibration p, the lifting data: for each g : b ⟶ p.obj c a lift hom g : src g ⟶ c, together with the statement that it is the only lift.

Main statements

    DiscreteFibration.map_injective and DiscreteFibration.faithful: a discrete fibration is faithful.

    isHomLift_iff_arrow_mk_eq: mathlib's Functor.IsHomLift is equality of arrows.

    DiscreteFibration.isCartesian, DiscreteFibration.isPreFibered and DiscreteFibration.isFibered: every morphism is cartesian, so a discrete fibration is a fibred category.

    DiscreteFibration.fiber_eq_of_hom and DiscreteFibration.fiber_hom_ext: the fibres are discrete categories.

Implementation notes

Lifts are unique, so DiscreteFibration p is a Subsingleton: carrying it as data costs nothing, and it lets the fibre presheaf of Geb/Mathlib/CategoryTheory/DiscreteFibration/FiberPresheaf.lean be defined without Classical.choice.

eq_of_isHomLift_id and fiber_eq_of_hom route through Functor.Fiber.fiberInclusion rather than the subtype projections of Functor.Fiber, which is semireducible: a goal mentioning b.1 is not type-correct at implicit transparency and stops rw and simp.

References

    [LoregianRiehl2018]

    [nLabDiscreteFibration]

Tags

discrete fibration, fibred category, cartesian morphism, fibre

@[expose] public sectionuniverse v₁ v₂ u₁ u₂namespace CategoryTheoryvariable {C : Type u₁} [Category.{v₁} C] {B : Type u₂} [Category.{v₂} B]

Lifting data for p: for every g : b ⟶ p.obj c a lift hom g : src g ⟶ c over g, unique among all lifts. The base-side eqToHom is forced by the bundle presentation (objects of C are only propositionally over b); it vanishes in the family presentation Functor.CoElements below.

Domain of the lift of g.

The lift of g.

The domain of the lift of g lies over the domain of g.

The lift of g lies over g.

Uniqueness of lifts, as an equality in Σ c', c' ⟶ c.

structure DiscreteFibration (p : C B) where src : {b : B} {c : C}, (b p.obj c) C hom : {b : B} {c : C} (g : b p.obj c), src g c obj_src : {b : B} {c : C} (g : b p.obj c), p.obj (src g) = b map_hom : {b : B} {c : C} (g : b p.obj c), p.map (hom g) = eqToHom (obj_src g) g unique : {b : B} {c : C} (g : b p.obj c) {c' : C} (h : c' c) (e : p.obj c' = b), p.map h = eqToHom e g (c', h : Σ c', c' c) = src g, hom g
namespace DiscreteFibrationvariable {p : C B} (D : DiscreteFibration p)include D

The uniqueness clause with the source fixed: p reflects equality of parallel arrows, i.e. p is faithful.

theorem map_injective {c c' : C} {h₁ h₂ : c' c} (H : p.map h₁ = p.map h₂) : h₁ = h₂ := C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pc:Cc':Ch₁:c' ch₂:c' cH:p.map h₁ = p.map h₂h₁ = h₂ C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pc:Cc':Ch₁:c' ch₂:c' cH:p.map h₁ = p.map h₂h:c', h₁ = c', h₂h₁ = h₂ All goals completed! 🐙

A discrete fibration is faithful.

theorem faithful : p.Faithful := fun H => D.map_injective H

Uniqueness of the source of a lift.

theorem src_eq {b : B} {c c' : C} (g : b p.obj c) (h : c' c) (e : p.obj c' = b) (H : p.map h = eqToHom e g) : D.src g = c' := (congrArg Sigma.fst (D.unique g h e H)).symm

The lift of an identity is an identity.

theorem src_id (c : C) : D.src (𝟙 (p.obj c)) = c := D.src_eq _ (𝟙 c) rfl (C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pc:Cp.map (𝟙 c) = eqToHom 𝟙 (p.obj c) All goals completed! 🐙)

Lifting data is unique: DiscreteFibration p is a mere proposition.

instance : Subsingleton (DiscreteFibration p) := C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pSubsingleton (DiscreteFibration p) C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration p (a b : DiscreteFibration p), a = b C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pD₁:DiscreteFibration pD₂:DiscreteFibration pD₁ = D₂ C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pD₁:DiscreteFibration pD₂:DiscreteFibration ph: {b : B} {c : C} (g : b p.obj c), D₁.src g, D₁.hom g = D₂.src g, D₂.hom gD₁ = D₂ C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pD₂:DiscreteFibration psrc₁:{b : B} {c : C} (b p.obj c) Chom₁:{b : B} {c : C} (g : b p.obj c) src₁ g cobj_src✝: {b : B} {c : C} (g : b p.obj c), p.obj (src₁ g) = bmap_hom✝: {b : B} {c : C} (g : b p.obj c), p.map (hom₁ g) = eqToHom gunique✝: {b : B} {c : C} (g : b p.obj c) {c' : C} (h : c' c) (e : p.obj c' = b), p.map h = eqToHom e g c', h = src₁ g, hom₁ gh: {b : B} {c : C} (g : b p.obj c), { src := src₁, hom := hom₁, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ }.src g, { src := src₁, hom := hom₁, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ }.hom g = D₂.src g, D₂.hom g{ src := src₁, hom := hom₁, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ } = D₂ C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration psrc₁:{b : B} {c : C} (b p.obj c) Chom₁:{b : B} {c : C} (g : b p.obj c) src₁ g cobj_src✝¹: {b : B} {c : C} (g : b p.obj c), p.obj (src₁ g) = bmap_hom✝¹: {b : B} {c : C} (g : b p.obj c), p.map (hom₁ g) = eqToHom gunique✝¹: {b : B} {c : C} (g : b p.obj c) {c' : C} (h : c' c) (e : p.obj c' = b), p.map h = eqToHom e g c', h = src₁ g, hom₁ gsrc₂:{b : B} {c : C} (b p.obj c) Chom₂:{b : B} {c : C} (g : b p.obj c) src₂ g cobj_src✝: {b : B} {c : C} (g : b p.obj c), p.obj (src₂ g) = bmap_hom✝: {b : B} {c : C} (g : b p.obj c), p.map (hom₂ g) = eqToHom gunique✝: {b : B} {c : C} (g : b p.obj c) {c' : C} (h : c' c) (e : p.obj c' = b), p.map h = eqToHom e g c', h = src₂ g, hom₂ gh: {b : B} {c : C} (g : b p.obj c), { src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ }.src g, { src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ }.hom g = { src := src₂, hom := hom₂, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ }.src g, { src := src₂, hom := hom₂, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ }.hom g{ src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ } = { src := src₂, hom := hom₂, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ } C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration psrc₁:{b : B} {c : C} (b p.obj c) Chom₁:{b : B} {c : C} (g : b p.obj c) src₁ g cobj_src✝¹: {b : B} {c : C} (g : b p.obj c), p.obj (src₁ g) = bmap_hom✝¹: {b : B} {c : C} (g : b p.obj c), p.map (hom₁ g) = eqToHom gunique✝¹: {b : B} {c : C} (g : b p.obj c) {c' : C} (h : c' c) (e : p.obj c' = b), p.map h = eqToHom e g c', h = src₁ g, hom₁ gsrc₂:{b : B} {c : C} (b p.obj c) Chom₂:{b : B} {c : C} (g : b p.obj c) src₂ g cobj_src✝: {b : B} {c : C} (g : b p.obj c), p.obj (src₂ g) = bmap_hom✝: {b : B} {c : C} (g : b p.obj c), p.map (hom₂ g) = eqToHom gunique✝: {b : B} {c : C} (g : b p.obj c) {c' : C} (h : c' c) (e : p.obj c' = b), p.map h = eqToHom e g c', h = src₂ g, hom₂ gh: {b : B} {c : C} (g : b p.obj c), { src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ }.src g, { src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ }.hom g = { src := src₂, hom := hom₂, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ }.src g, { src := src₂, hom := hom₂, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ }.hom ghs:src₁ = src₂{ src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ } = { src := src₂, hom := hom₂, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ } C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration psrc₁:{b : B} {c : C} (b p.obj c) Chom₁:{b : B} {c : C} (g : b p.obj c) src₁ g cobj_src✝¹: {b : B} {c : C} (g : b p.obj c), p.obj (src₁ g) = bmap_hom✝¹: {b : B} {c : C} (g : b p.obj c), p.map (hom₁ g) = eqToHom gunique✝¹: {b : B} {c : C} (g : b p.obj c) {c' : C} (h : c' c) (e : p.obj c' = b), p.map h = eqToHom e g c', h = src₁ g, hom₁ ghom₂:{b : B} {c : C} (g : b p.obj c) src₁ g cobj_src✝: {b : B} {c : C} (g : b p.obj c), p.obj (src₁ g) = bmap_hom✝: {b : B} {c : C} (g : b p.obj c), p.map (hom₂ g) = eqToHom gunique✝: {b : B} {c : C} (g : b p.obj c) {c' : C} (h : c' c) (e : p.obj c' = b), p.map h = eqToHom e g c', h = src₁ g, hom₂ gh: {b : B} {c : C} (g : b p.obj c), { src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ }.src g, { src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ }.hom g = { src := src₁, hom := hom₂, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ }.src g, { src := src₁, hom := hom₂, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ }.hom g{ src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ } = { src := src₁, hom := hom₂, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ } C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration psrc₁:{b : B} {c : C} (b p.obj c) Chom₁:{b : B} {c : C} (g : b p.obj c) src₁ g cobj_src✝¹: {b : B} {c : C} (g : b p.obj c), p.obj (src₁ g) = bmap_hom✝¹: {b : B} {c : C} (g : b p.obj c), p.map (hom₁ g) = eqToHom gunique✝¹: {b : B} {c : C} (g : b p.obj c) {c' : C} (h : c' c) (e : p.obj c' = b), p.map h = eqToHom e g c', h = src₁ g, hom₁ ghom₂:{b : B} {c : C} (g : b p.obj c) src₁ g cobj_src✝: {b : B} {c : C} (g : b p.obj c), p.obj (src₁ g) = bmap_hom✝: {b : B} {c : C} (g : b p.obj c), p.map (hom₂ g) = eqToHom gunique✝: {b : B} {c : C} (g : b p.obj c) {c' : C} (h : c' c) (e : p.obj c' = b), p.map h = eqToHom e g c', h = src₁ g, hom₂ gh: {b : B} {c : C} (g : b p.obj c), { src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ }.src g, { src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ }.hom g = { src := src₁, hom := hom₂, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ }.src g, { src := src₁, hom := hom₂, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ }.hom ghh:hom₁ = hom₂{ src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ } = { src := src₁, hom := hom₂, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ } C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration psrc₁:{b : B} {c : C} (b p.obj c) Chom₁:{b : B} {c : C} (g : b p.obj c) src₁ g cobj_src✝¹: {b : B} {c : C} (g : b p.obj c), p.obj (src₁ g) = bmap_hom✝¹: {b : B} {c : C} (g : b p.obj c), p.map (hom₁ g) = eqToHom gunique✝¹: {b : B} {c : C} (g : b p.obj c) {c' : C} (h : c' c) (e : p.obj c' = b), p.map h = eqToHom e g c', h = src₁ g, hom₁ gobj_src✝: {b : B} {c : C} (g : b p.obj c), p.obj (src₁ g) = bmap_hom✝: {b : B} {c : C} (g : b p.obj c), p.map (hom₁ g) = eqToHom gunique✝: {b : B} {c : C} (g : b p.obj c) {c' : C} (h : c' c) (e : p.obj c' = b), p.map h = eqToHom e g c', h = src₁ g, hom₁ gh: {b : B} {c : C} (g : b p.obj c), { src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ }.src g, { src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ }.hom g = { src := src₁, hom := hom₁, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ }.src g, { src := src₁, hom := hom₁, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ }.hom g{ src := src₁, hom := hom₁, obj_src := obj_src✝¹, map_hom := map_hom✝¹, unique := unique✝¹ } = { src := src₁, hom := hom₁, obj_src := obj_src✝, map_hom := map_hom✝, unique := unique✝ } All goals completed! 🐙
end DiscreteFibration

Mathlib's IsHomLift

Mathlib's IsHomLift is the proposition Arrow.mk (p.map φ) = Arrow.mk f.

theorem isHomLift_iff_arrow_mk_eq (p : C B) {R S : B} {a b : C} (f : R S) (φ : a b) : p.IsHomLift f φ Arrow.mk (p.map φ) = Arrow.mk f := C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BR:BS:Ba:Cb:Cf:R Sφ:a bp.IsHomLift f φ Arrow.mk (p.map φ) = Arrow.mk f C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BR:BS:Ba:Cb:Cf:R Sφ:a bp.IsHomLift f φ Arrow.mk (p.map φ) = Arrow.mk fC:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BR:BS:Ba:Cb:Cf:R Sφ:a bArrow.mk (p.map φ) = Arrow.mk f p.IsHomLift f φ C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BR:BS:Ba:Cb:Cf:R Sφ:a bp.IsHomLift f φ Arrow.mk (p.map φ) = Arrow.mk f C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BR:BS:Ba:Cb:Cf:R Sφ:a bh:p.IsHomLift f φArrow.mk (p.map φ) = Arrow.mk f All goals completed! 🐙 C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BR:BS:Ba:Cb:Cf:R Sφ:a bArrow.mk (p.map φ) = Arrow.mk f p.IsHomLift f φ C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BR:BS:Ba:Cb:Cf:R Sφ:a bh:Arrow.mk (p.map φ) = Arrow.mk fp.IsHomLift f φ C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BR:BS:Ba:Cb:Cf:R Sφ:a bh:Arrow.mk (p.map φ) = Arrow.mk fhR:p.obj a = RhS:p.obj b = Shf:p.map φ = eqToHom hR f eqToHom p.IsHomLift f φ All goals completed! 🐙
namespace DiscreteFibrationvariable {p : C B} (D : DiscreteFibration p)include D

The lift of g as an arrow of C.

def liftArrow {b : B} {c : C} (g : b p.obj c) : Arrow C := Arrow.mk (D.hom g)

The image of the lift of g is g, as an equality of arrows.

theorem arrow_mk_map_hom {b : B} {c : C} (g : b p.obj c) : Arrow.mk (p.map (D.hom g)) = Arrow.mk g := (Arrow.mk_eq_mk_iff _ _).2 D.obj_src g, rfl, C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pb:Bc:Cg:b p.obj cp.map (D.hom g) = eqToHom g eqToHom All goals completed! 🐙

The lift of g lies over g in mathlib's sense.

theorem isHomLift_hom {b : B} {c : C} (g : b p.obj c) : p.IsHomLift g (D.hom g) := (isHomLift_iff_arrow_mk_eq p g (D.hom g)).2 (D.arrow_mk_map_hom g)

Uniqueness of lifts, Arrow-style.

theorem eq_liftArrow {b : B} {c : C} (g : b p.obj c) {c' : C} (h : c' c) (hh : Arrow.mk (p.map h) = Arrow.mk g) : Arrow.mk h = D.liftArrow g := C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pb:Bc:Cg:b p.obj cc':Ch:c' chh:Arrow.mk (p.map h) = Arrow.mk gArrow.mk h = D.liftArrow g C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pb:Bc:Cg:b p.obj cc':Ch:c' chh:Arrow.mk (p.map h) = Arrow.mk ge:p.obj c' = bhY:p.obj c = p.obj chf:p.map h = eqToHom e g eqToHom Arrow.mk h = D.liftArrow g C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pb:Bc:Cg:b p.obj cc':Ch:c' chh:Arrow.mk (p.map h) = Arrow.mk ge:p.obj c' = bhY:p.obj c = p.obj chf:p.map h = eqToHom e g eqToHom hu:c', h = D.src g, D.hom gArrow.mk h = D.liftArrow g C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pb:Bc:Cg:b p.obj cc':Ch:c' chh:Arrow.mk (p.map h) = Arrow.mk ge:p.obj c' = bhY:p.obj c = p.obj chf:p.map h = eqToHom e g eqToHom hu:c', h = D.src g, D.hom gh1:c' = D.src gh2:h D.hom gArrow.mk h = D.liftArrow g C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pb:Bc:Cg:b p.obj cc':Ch:c' chh:Arrow.mk (p.map h) = Arrow.mk ge:p.obj c' = bhY:p.obj c = p.obj chf:p.map h = eqToHom e g eqToHom hu:c', h = D.src g, D.hom gh1:c' = D.src gh2:h D.hom gArrow.mk h = Arrow.mk (D.hom g) C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pb:Bc:Cg:b p.obj chY:p.obj c = p.obj ch:D.src g chh:Arrow.mk (p.map h) = Arrow.mk ge:p.obj (D.src g) = bhf:p.map h = eqToHom e g eqToHom hu:D.src g, h = D.src g, D.hom gh2:h D.hom gArrow.mk h = Arrow.mk (D.hom g) All goals completed! 🐙

A morphism lying over an identity has equal endpoints.

theorem eq_of_isHomLift_id {S : B} {a b : C} (ψ : a b) [p.IsHomLift (𝟙 S) ψ] : a = b := (D.src_eq (eqToHom (IsHomLift.codomain_eq p (𝟙 S) ψ).symm) ψ (IsHomLift.domain_eq p (𝟙 S) ψ) (C:Type u₁inst✝²:Category.{v₁, u₁} CB:Type u₂inst✝¹:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pS:Ba:Cb:Cψ:a binst✝:p.IsHomLift (𝟙 S) ψp.map ψ = eqToHom eqToHom All goals completed! 🐙)).symm.trans (D.src_eq (eqToHom (IsHomLift.codomain_eq p (𝟙 S) ψ).symm) (𝟙 b) (IsHomLift.codomain_eq p (𝟙 S) ψ) (C:Type u₁inst✝²:Category.{v₁, u₁} CB:Type u₂inst✝¹:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pS:Ba:Cb:Cψ:a binst✝:p.IsHomLift (𝟙 S) ψp.map (𝟙 b) = eqToHom eqToHom All goals completed! 🐙))

The endpoints of a morphism of a fibre agree. With fiber_hom_ext below, the fibres of a discrete fibration are discrete categories.

theorem fiber_eq_of_hom {S : B} {a b : p.Fiber S} (φ : a b) : a = b := Functor.Fiber.fiberInclusion_obj_inj (D.eq_of_isHomLift_id (S := S) (Functor.Fiber.fiberInclusion.map φ))

Parallel morphisms of a fibre agree, since p is faithful.

theorem fiber_hom_ext {S : B} {a b : p.Fiber S} (φ ψ : a b) : φ = ψ := Functor.Fiber.hom_ext (D.map_injective ((IsHomLift.fac' p (𝟙 S) (Functor.Fiber.fiberInclusion.map φ)).trans (IsHomLift.fac' p (𝟙 S) (Functor.Fiber.fiberInclusion.map ψ)).symm))

Every morphism over f is cartesian in mathlib's sense: uniqueness of lifts supplies the universal property outright.

theorem isCartesian {R S : B} {a b : C} (f : R S) (φ : a b) [p.IsHomLift f φ] : p.IsCartesian f φ where universal_property {a'} φ' _ := C:Type u₁inst✝²:Category.{v₁, u₁} CB:Type u₂inst✝¹:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pR:BS:Ba:Cb:Cf:R Sφ:a binst✝:p.IsHomLift f φa':Cφ':a' bx✝:p.IsHomLift f φ'∃! χ, p.IsHomLift (𝟙 R) χ χ φ = φ' C:Type u₁inst✝²:Category.{v₁, u₁} CB:Type u₂inst✝¹:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pR:BS:Ba:Cb:Cf:R Sφ:a binst✝:p.IsHomLift f φa':Cφ':a' bx✝:p.IsHomLift f φ'key:a', φ' = a, φ∃! χ, p.IsHomLift (𝟙 R) χ χ φ = φ' C:Type u₁inst✝²:Category.{v₁, u₁} CB:Type u₂inst✝¹:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pR:BS:Ba:Cb:Cf:R Sφ:a binst✝:p.IsHomLift f φa':Cφ':a' bx✝:p.IsHomLift f φ'key:a', φ' = a, φha:a' = a:φ' φ∃! χ, p.IsHomLift (𝟙 R) χ χ φ = φ' C:Type u₁inst✝²:Category.{v₁, u₁} CB:Type u₂inst✝¹:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pR:BS:Bb:Cf:R Sa':Cφ':a' bx✝:p.IsHomLift f φ'φ:a' binst✝:p.IsHomLift f φkey:a', φ' = a', φ:φ' φ∃! χ, p.IsHomLift (𝟙 R) χ χ φ = φ' C:Type u₁inst✝²:Category.{v₁, u₁} CB:Type u₂inst✝¹:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pR:BS:Bb:Cf:R Sa':Cφ':a' bx✝:p.IsHomLift f φ'inst✝:p.IsHomLift f φ'key:a', φ' = a', φ':φ' φ'∃! χ, p.IsHomLift (𝟙 R) χ χ φ' = φ' C:Type u₁inst✝²:Category.{v₁, u₁} CB:Type u₂inst✝¹:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pR:BS:Bb:Cf:R Sa':Cφ':a' bx✝:p.IsHomLift f φ'inst✝:p.IsHomLift f φ'key:a', φ' = a', φ':φ' φ'χ:a' a':(fun χ p.IsHomLift (𝟙 R) χ χ φ' = φ') χp.map χ = p.map (𝟙 a') C:Type u₁inst✝²:Category.{v₁, u₁} CB:Type u₂inst✝¹:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pR:BS:Bb:Cf:R Sa':Cφ':a' bx✝:p.IsHomLift f φ'inst✝:p.IsHomLift f φ'key:a', φ' = a', φ':φ' φ'χ:a' a':(fun χ p.IsHomLift (𝟙 R) χ χ φ' = φ') χthis:p.IsHomLift (𝟙 R) χp.map χ = p.map (𝟙 a') C:Type u₁inst✝²:Category.{v₁, u₁} CB:Type u₂inst✝¹:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pR:BS:Bb:Cf:R Sa':Cφ':a' bx✝:p.IsHomLift f φ'inst✝:p.IsHomLift f φ'key:a', φ' = a', φ':φ' φ'χ:a' a':(fun χ p.IsHomLift (𝟙 R) χ χ φ' = φ') χthis:p.IsHomLift (𝟙 R) χp.map χ = 𝟙 (p.obj a') All goals completed! 🐙

Every object of C admits a cartesian lift of every morphism into its image.

theorem isPreFibered : p.IsPreFibered where exists_isCartesian' f := D.src f, D.hom f, have := D.isHomLift_hom f; D.isCartesian _ _

A discrete fibration is a fibred category.

theorem isFibered : p.IsFibered where toIsPreFibered := D.isPreFibered comp := C:Type u₁inst✝¹:Category.{v₁, u₁} CB:Type u₂inst✝:Category.{v₂, u₂} Bp:C BD:DiscreteFibration p {R S T : B} (f : R S) (g : S T) {a b c : C} (φ : a b) (ψ : b c) [p.IsCartesian f φ] [p.IsCartesian g ψ], p.IsCartesian (f g) (φ ψ) C:Type u₁inst✝³:Category.{v₁, u₁} CB:Type u₂inst✝²:Category.{v₂, u₂} Bp:C BD:DiscreteFibration pR✝:BS✝:BT✝:Bf:R✝ S✝g:S✝ T✝a✝:Cb✝:Cc✝:Cφ:a✝ b✝ψ:b✝ c✝inst✝¹:p.IsCartesian f φinst✝:p.IsCartesian g ψp.IsCartesian (f g) (φ ψ) All goals completed! 🐙
end DiscreteFibrationend CategoryTheory