diff --git a/HB/common/database.elpi b/HB/common/database.elpi index d583b4c37..d0ed789d4 100644 --- a/HB/common/database.elpi +++ b/HB/common/database.elpi @@ -179,12 +179,20 @@ toposort-proj Proj ES In Out :- !, toposort-proj.acc Proj ES [] In Out. pred topo-find i:B, o:A. pred toposort-proj.acc i:(A -> B -> prop), i:list (pair B B), i:list B, i:list A, o:list A. toposort-proj.acc _ ES Acc [] Out :- !, - std.map {std.toposort ES Acc} topo-find Out. + std.map {std.toposort ES Acc} topo-find-all Out. toposort-proj.acc Proj ES Acc [A|In] Out :- std.do![ Proj A B, topo-find B A => toposort-proj.acc Proj ES [B|Acc] In Out ]. +pred topo-find-all i:B, o:A. +topo-find-all B A :- std.do! [ + std.findall (topo-find B C_) L, + % if there were dusplicates, we ensure we keep the most instantiated, eg + % (triple m [X,Y] t) v.s. (triple m [a,b] t) + std.assert! (std.forall L (x\ x = topo-find B A)) "topofind bad", +]. + % Classes can be topologically sorted according to the subclass relation pred toposort-classes.mk-class-edge i:prop, o:pair classname classname. toposort-classes.mk-class-edge (sub-class C1 C2 _ _) (pr C2 C1). @@ -438,11 +446,14 @@ structure-nparams Structure NParams :- class-def (class Class Structure _), factory-nparams Class NParams. +pred factory?-split i:term, o:factoryname, o:list term, o:term, o:list term. +factory?-split (app[global GR|Args]) F [global GR|Params] T Rest :- + factory-alias->gref GR F, factory-nparams F NP, !, + std.split-at NP Args Params [T|Rest]. + pred factory? i:term, o:w-args factoryname. factory? S (triple F Params T) :- - not (var S), !, - safe-dest-app S (global GR) Args, factory-alias->gref GR F, factory-nparams F NP, !, - std.split-at NP Args Params [T|_]. + factory?-split S F [_|Params] T _. % [find-max-classes Mixins Classes] states that Classes is a list of classes % which contain all the mixins in Mixins. @@ -462,3 +473,8 @@ find-max-classes [M|Mixins] [C|Classes] :- ]. find-max-classes [M|_] _ :- coq.error "HB: cannot find a class containing mixin" M. +pred is-subject-lifter i:term, o:int, o:classname. +is-subject-lifter (global (const C)) N Class :- exported-op M _ C, wrapper-mixin _ (const C) _, factory-nparams M N, mixin-first-class M Class. +is-subject-lifter (app[global (const C)|_]) N Class :- exported-op M _ C, wrapper-mixin _ (const C) _, factory-nparams M N, mixin-first-class M Class. +is-subject-lifter (global GR) N Class :- tag GR Class N, wrapper-mixin _ GR _. +is-subject-lifter (app[global GR|_]) N Class :- tag GR Class N, wrapper-mixin _ GR _. diff --git a/HB/common/phant-abbreviation.elpi b/HB/common/phant-abbreviation.elpi index 943c30c74..e2451a6d8 100644 --- a/HB/common/phant-abbreviation.elpi +++ b/HB/common/phant-abbreviation.elpi @@ -27,6 +27,12 @@ add-abbreviation N (private.phant-term AL T1) C Abbrev :- std.do! [ private.build-abbreviation 0 (global (const C)) AL NParams AbbrevT, @global! => log.coq.notation.add-abbreviation N NParams AbbrevT tt Abbrev, ]. +pred add-abbreviation2 i:gref, i:string, i:phant-term, o:constant, o:abbreviation. +add-abbreviation2 GR N (private.phant-term _ _) C Abbrev :- std.do! [ + NC is "phant_" ^ N, + log.coq.env.add-const-noimplicits NC (global GR) _ @transparent! C, + @global! => log.coq.notation.add-abbreviation N 0 (global (const C)) tt Abbrev, +]. % [of-gref WithCopy GR RealMixinArgs PT] % builds a phant-term taking all parameters, diff --git a/HB/common/synthesis.elpi b/HB/common/synthesis.elpi index c596fc5c4..cced84833 100644 --- a/HB/common/synthesis.elpi +++ b/HB/common/synthesis.elpi @@ -74,6 +74,13 @@ infer-all-args-let Ps T GR X Diag :- std.do! [ private.instantiate-all-args-let FT T X Diag, ]. +pred try-infer-all-args-let i:list term, i:term, i:gref, o:term. +try-infer-all-args-let Ps T GR X :- std.do! [ + coq.env.typeof GR Ty, + coq.mk-eta (-1) Ty (global GR) EtaF, + coq.subst-fun {std.append Ps [T]} EtaF FT, + private.try-instantiate-all-args-let FT T X, +]. % [assert!-infer-mixin TheType M Out] infers one mixin M on TheType and % aborts with an error message if the mixin cannot be inferred @@ -103,6 +110,17 @@ under-mixin-src-from-factory.do! TheType TheFactory LP :- std.do! [ MLClauses => std.do! LP ]. + +% Given TheType makes the provided list of mixins and instances +% available for inference. +pred under-these-mixin-src.do! i:term, i:list mixinname, i:list constant, o:list prop, i:list prop. +under-these-mixin-src.do! TheType ML TheMixins ClausesHas LP :- std.do! [ + std.map2 ML TheMixins (m\mi\c\ c = mixin-src TheType m (global (const mi))) MLClauses, + std.map-filter MLClauses mixin-src->has-mixin-instance ClausesHas, + MLClauses => std.do! LP +]. + + % Given TheType and a factory instance (on it), builds all the *new* mixins % provided by the factory available for and passes them to the given % continuation @@ -242,6 +260,7 @@ instantiate-all-these-mixin-args (fun _ Tm F) T ML R :- coq.safe-dest-app Tm (global TmGR) _, factory-alias->gref TmGR M, std.mem! ML M, + factory? Tm (triple _ _ Subj), Subj = T, % check the subject is T (do not pass T to factory?) !, mixin-for T M X, !, instantiate-all-these-mixin-args (F X) T ML R. @@ -261,6 +280,15 @@ instantiate-all-args-let (fun N Tm F) T (let N Tm X R) Diag :- !, std.do! [ ]. instantiate-all-args-let F _ F ok. +pred try-instantiate-all-args-let i:term, i:term, o:term. +try-instantiate-all-args-let (fun N Tm F) T (let N Tm X R) :- !, std.do! [ + coq.safe-dest-app Tm (global TmGR) _, + factory-alias->gref TmGR M, + (mixin-for T M X ; true), + (@pi-def N Tm X m\ try-instantiate-all-args-let (F m) T (R m)), +]. +try-instantiate-all-args-let F _ F. + % [structure-instance->mixin-srcs TheType Structure] finds a CS instance for % Structure on TheType (if any) and builds mixin-src clauses for all the mixins % which can be candidates from that class instance. It finds instances which are diff --git a/HB/common/utils-synterp.elpi b/HB/common/utils-synterp.elpi index 73932c1a4..9a6900b3c 100644 --- a/HB/common/utils-synterp.elpi +++ b/HB/common/utils-synterp.elpi @@ -24,6 +24,8 @@ with-attributes P :- att "primitive" bool, att "non_forgetful_inheritance" bool, att "hnf" bool, + att "wrapper" bool, + att "unsafe.univ" bool, ] Opts, !, Opts => (save-docstring, P). diff --git a/HB/common/utils.elpi b/HB/common/utils.elpi index de87dc33f..de4cad12f 100644 --- a/HB/common/utils.elpi +++ b/HB/common/utils.elpi @@ -76,7 +76,7 @@ gref->modname GR NComp Sep ModName :- std.length Path Len, if (Len >= NComp) true (coq.error "Not enough enclosing modules for" {coq.gref->string GR}), std.take NComp Mods L, - std.string.concat Sep {std.rev L} ModName. + std.string.concat Sep {std.rev [{std.any->string {new_int}}|L]} ModName. pred gref->modname-label i:gref, i:int, i:string, o:string. gref->modname-label GR NComp Sep ModName :- coq.gref->path GR Path, @@ -293,7 +293,7 @@ pack? (indc K) C :- coq.env.indc K _ _ _ KTy, prod-last-gref KTy (indt I), % TODO: use new API class-def (class C (indt I) _). -pred distribute-w-params i:list-w-params A, o:list (one-w-params A). +pred distribute-w-params i:w-params (list A), o:list (w-params A). distribute-w-params (w-params.cons N T F) L :- pi x\ distribute-w-params (F x) (L1 x), std.map (L1 x) (bind-cons N T x) L. distribute-w-params (w-params.nil N T F) L :- @@ -315,6 +315,46 @@ re-enable-id-phant T T1 :- (pi f1 f2 t v\ copy {{lib:@hb.ignore_disabled lp:t lp:f1 lp:v lp:f2}} {{lib:@hb.ignore lp:t lp:v}} :- !) => copy T T1. +pred disable-id-phant-indt-decl i:indt-decl, o:indt-decl. +disable-id-phant-indt-decl D D1 :- + (pi fresh fresh1 t v\ copy {{lib:@hb.id lp:t lp:v}} {{lib:@hb.id_disabled lp:t lp:fresh lp:v lp:fresh1}} :- !) => + (pi fresh fresh1 t v\ copy {{lib:@hb.ignore lp:t lp:v}} {{lib:@hb.ignore_disabled lp:t lp:fresh lp:v lp:fresh1}} :- !) => + copy-indt-decl D D1. + +pred re-enable-id-phant-indt-decl i:indt-decl, o:indt-decl. +re-enable-id-phant-indt-decl D D1 :- + (pi f1 f2 t v\ copy {{lib:@hb.id_disabled lp:t lp:f1 lp:v lp:f2}} {{lib:@hb.id lp:t lp:v}} :- !) => + (pi f1 f2 t v\ copy {{lib:@hb.ignore_disabled lp:t lp:f1 lp:v lp:f2}} {{lib:@hb.ignore lp:t lp:v}} :- !) => + copy-indt-decl D D1. + + +pred failsafe-structure-inference i:term, o:term. +failsafe-structure-inference T T1 :- + (pi T T2 F_Params F_Params1 Args Args1 Subject Subject1 NP ArgsOp ArgsOp1 OP S\ + copy T T2 :- + factory?-split T _ F_Params Subject Args, + std.map F_Params copy F_Params1, + std.map Args copy Args1, + is-subject-lifter Subject NP Class, + coq.safe-dest-app Subject OP ArgsOp, + std.nth NP ArgsOp S, + (var S ; name S), % TODO: should be the subject of the structure, not a random name + !, + eta-structure-record S NP Class ArgsOp ArgsOp1, + coq.mk-app OP ArgsOp1 Subject1, + coq.mk-app (app F_Params1) [Subject1|Args1] T2) => + copy T T1. + +pred eta-structure-record i:term, i:int, i:classname, i:list term, o:list term. +eta-structure-record S NP Class L L1 :- + std.split-at NP L Params [_|Rest], + class-def (class Class Structure _), + get-constructor Structure K, + std.map Params copy Params1, + std.map Rest copy Rest1, + coq.mk-app {coq.env.global K} {std.append Params1 [S,_]} EtaS, + std.append Params1 [EtaS|Rest1] L1. + pred prod-last i:term, o:term. prod-last (prod N S X) Y :- !, @pi-decl N S x\ prod-last (X x) Y. prod-last X X :- !. @@ -329,3 +369,12 @@ saturate-type-constructor T ET :- coq.typecheck T TH ok, coq.count-prods TH N, coq.mk-app T {coq.mk-n-holes N} ET. + +pred with-unsafe-univ i:prop. +with-unsafe-univ P :- get-option "unsafe.univ" tt, !, + coq.option.get ["Universe","Checking"] Old, + coq.option.set ["Universe","Checking"] (coq.option.bool ff), + P, + coq.option.set ["Universe","Checking"] Old. +with-unsafe-univ P :- P. + \ No newline at end of file diff --git a/HB/context.elpi b/HB/context.elpi index 4b04e5f0b..627106066 100644 --- a/HB/context.elpi +++ b/HB/context.elpi @@ -57,6 +57,38 @@ namespace private { % to the corresponding mixin using mixin-for pred postulate-mixin i:term, i:w-args mixinname, i:triple (list constant) (list prop) (list (w-args mixinname)), o:triple (list constant) (list prop) (list (w-args mixinname)). +postulate-mixin TheType (triple M Ps T) (triple CL MSL MLwP) (triple OutCL [MC|MSL] [NewMwP|MLwP]) :- wrapper-mixin M _ _, !, MSL => std.do! [ + NameVar is "local_mixin_private_" ^ {gref->modname M 2 "_"}, + NameMixin is "local_mixin_" ^ {gref->modname M 2 "_"}, + + if-verbose (coq.say "HB: postulate and wrap" NameVar "on" {coq.term->string T}), + + synthesis.infer-all-gref-deps Ps T M TySkel, + % was synthesis.infer-all-mixin-args Ps T M TySkel, + % if-verbose (coq.say "HB: postulate-mixin checking" TySkel), + % std.assert-ok! (coq.typecheck Ty _) "postulate-mixin: Ty illtyped", + std.assert-ok! (coq.elaborate-ty-skeleton TySkel _ Ty) + "postulate-mixin: Ty illtyped", + + Ty = app[global M|Args], + factory-constructor M K, + coq.mk-app (global K) Args KArgs, + std.assert-ok! (coq.typecheck KArgs {{ lp:VarTy -> _ }}) "brrr", + + log.coq.env.add-section-variable-noimplicits NameVar VarTy V, + + coq.mk-app KArgs [global (const V)] TheMixin, + + log.coq.env.add-const-noimplicits NameMixin TheMixin Ty @transparent! C, + + factory? Ty NewMwP, + + declare-instances-from-postulated-mixin TheType M T C MC NewCL, + + std.append CL NewCL OutCL, + +]. + postulate-mixin TheType (triple M Ps T) (triple CL MSL MLwP) (triple OutCL [MC|MSL] [NewMwP|MLwP]) :- MSL => std.do! [ Name is "local_mixin_" ^ {gref->modname M 2 "_"}, @@ -69,12 +101,22 @@ postulate-mixin TheType (triple M Ps T) (triple CL MSL MLwP) (triple OutCL [MC|M std.assert-ok! (coq.elaborate-ty-skeleton TySkel _ Ty) "postulate-mixin: Ty illtyped", log.coq.env.add-section-variable-noimplicits Name Ty C, + factory? Ty NewMwP, + declare-instances-from-postulated-mixin TheType M T C MC NewCL, + + std.append CL NewCL OutCL, + + ]. + +pred declare-instances-from-postulated-mixin i:term, i:mixinname, i:term, i:constant, o:prop, o:(list constant). +declare-instances-from-postulated-mixin TheType M T C MC NewCL :- std.do! [ + MC = mixin-src T M (global (const C)), MC => get-option "local" tt => instance.declare-all TheType {findall-classes-for [M]} NewCSL, std.map NewCSL snd NewCL, - std.append CL NewCL OutCL - ]. +]. + }} diff --git a/HB/factory.elpi b/HB/factory.elpi index 8ff726654..08835b367 100644 --- a/HB/factory.elpi +++ b/HB/factory.elpi @@ -219,6 +219,53 @@ declare-asset Arg AssetKind :- std.do! [ ) ]. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% auxiliary code for wrapper-mixin + +pred extract_from_record_decl i: (term -> gref -> prop), i:indt-decl, o:gref. +extract_from_record_decl P (parameter ID _ Ty R) Out :- + @pi-parameter ID Ty p\ + extract_from_record_decl P (R p) Out. +extract_from_record_decl P (record _ _ _ (field _ _ Ty (x\end-record))) GR0 :- + P Ty GR0. + +pred extract_from_rtty i: (term -> gref -> prop), i: term, o:gref. +extract_from_rtty P (prod N Ty TF) Out1 :- + @pi-decl N Ty p\ + extract_from_rtty P (TF p) Out1. +extract_from_rtty P Ty Gr :- P Ty Gr. + +pred xtr_fst_op i:term, o:gref. +xtr_fst_op Ty Gr1 :- + Ty = (app [global Gr0| _]), + factory-alias->gref Gr0 Gr1. + +pred xtr_snd_op i:term, o:gref. +xtr_snd_op Ty Gr :- + % TODO: use factory? from database.elpi + Ty = (app [global Gr0| Args]), + factory-alias->gref Gr0 Gr1, + factory-nparams Gr1 N, + std.nth N Args (app [global Gr| _]). + +pred extract_wrapped i:indt-decl, o:gref. +extract_wrapped In Out :- + extract_from_record_decl (extract_from_rtty xtr_fst_op) In Out. + +pred extract_subject i:indt-decl, o:gref. +extract_subject In Out :- + extract_from_record_decl (extract_from_rtty xtr_snd_op) In Out. + +pred wrapper_mixin_aux i:gref, o:gref, o:gref. +wrapper_mixin_aux XX Gr1 Gr2 :- + XX = (indt I), + coq.env.indt-decl I D, + extract_subject D Gr1, + extract_wrapped D Gr2. + +%%% end auxiliary code for wrapper-mixin +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + pred declare-mixin-or-factory i:list prop, i:list constant, i:list term, i:term, i:term, i:record-decl, i:list-w-params factoryname, i:id, i:asset. declare-mixin-or-factory MixinSrcClauses SectionCanonicalInstance @@ -229,6 +276,8 @@ declare-mixin-or-factory MixinSrcClauses SectionCanonicalInstance RDeclSkel = record "axioms_" Sort1 Kname Fields, std.assert-ok! (coq.elaborate-indt-decl-skeleton RDeclSkel RDecl) "record declaration illtyped", + % scheck-no-mixin-or-factory-occurs RDecl, + abstract-over-section TheParams TheType MixinSrcClauses SectionCanonicalInstance coq.abstract-indt-decl RDecl RDeclClosed _, @@ -255,6 +304,12 @@ declare-mixin-or-factory MixinSrcClauses SectionCanonicalInstance % TODO: should this be in the Exports module? + % if the wrapper option is on, build the wrapper clause + if (get-option "wrapper" tt) + ((wrapper_mixin_aux (indt R) NSbj WMxn), + (WrapperClauses = [wrapper-mixin (indt R) NSbj WMxn])) + (WrapperClauses = []), + if-verbose (coq.say {header} "declare notation Build"), GRDepsClauses => phant.of-gref ff GRK [] PhGRK, @@ -271,7 +326,7 @@ declare-mixin-or-factory MixinSrcClauses SectionCanonicalInstance if-verbose (coq.say {header} "start module Exports"), log.coq.env.begin-module "Exports" none, - std.flatten [Clauses, GRDepsClauses, [ + std.flatten [Clauses, GRDepsClauses, WrapperClauses, [ factory-constructor (indt R) GRK, factory-nparams (indt R) NParams, factory-builder-nparams BuildConst NParams, diff --git a/HB/instance.elpi b/HB/instance.elpi index 2eec1d08b..dc93e45c5 100644 --- a/HB/instance.elpi +++ b/HB/instance.elpi @@ -3,6 +3,7 @@ namespace instance { +% DEPRECATED % [declare-existing T F] equips T with all the canonical structures that can be % built using factory instance F pred declare-existing i:argument, i:argument. @@ -32,7 +33,7 @@ declare-const Name BodySkel TyWPSkel CSL :- std.do! [ % Do not open a section when it is not necessary (no parameters) % A side effect of opening a section is loosing meta data associated % with instances, in particular builder tags are lost - if-verbose (coq.say "HB: skipping section opening"), + if-verbose (coq.say "HB!: skipping section opening"), SectionBody = Body ) ( std.assert! (coq.next-synterp-action (begin-section SectionName)) "synterp code did not open section", @@ -66,16 +67,42 @@ declare-const Name BodySkel TyWPSkel CSL :- std.do! [ private.check-non-forgetful-inheritance TheType Factory, - private.declare-instance Factory TheType TheFactory Clauses CSL, - - % handle parameters via a section -- end - if (TyWP = arity _) true ( - if-verbose (coq.say {header} "closing instance section"), - log.coq.env.end-section-name SectionName - ), + if (current-mode (builder-from TheType TheFactoryForBuilderSection FGR _)) + % instance in a builder section %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + (std.do![ + if (get-option "local" tt) + (coq.error "HB: declare-instance: cannot make builders local. If you want temporary instances, make an alias, e.g. with let T' := T") true, + + private.declare-canonical-instances-from-factory-and-local-builders + Factory TheType TheFactory TheFactoryForBuilderSection FGR Clauses CSL, + + private.close-section-if-has-params TyWP SectionName, + ]) + % instance in regular section %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + (std.do![ + + % derive all mixins the factory provides + private.declare-mixins-from-factory Factory TheType TheFactory ML TheMixins, + + % regular instance %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if (get-option "wrapper" ff ; not(is-subject-lifter TheType _ _)) + % regular subject %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + (private.declare-regular-inst TheType ML TheMixins TyWP SectionName ClausesHas CSL) + % wrapper %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + (private.declare-wrapper-inst TheType ML TheMixins TyWP SectionName ClausesHas CSL) + , + + % shared to all branches + if (get-option "export" tt) + (coq.env.current-library File, + std.map CSL (x\r\ sigma i c\ x = pr i c, r = instance-to-export File i c) ClausesExp) + (ClausesExp = []), + + std.append ClausesHas ClausesExp Clauses, + ]), % we accumulate clauses now that the section is over - acc-clauses current Clauses + acc-clauses current Clauses ]. % [declare-all T CL MCSTL] given a type T and a list of class definition @@ -256,6 +283,7 @@ namespace private { shorten coq.{ term->gref, subst-fun, safe-dest-app, mk-app, mk-eta, subst-prod }. +% DEPRECATED pred declare-instance i:factoryname, i:term, i:term, o:list prop, o:list (pair id constant). declare-instance Factory T F Clauses CSL :- @@ -274,11 +302,11 @@ declare-instance Factory T F Clauses CSL :- (Clauses2 = []), std.append Clauses1 Clauses2 Clauses. -% [add-mixin T F _ M Cl] adds a constant being the mixin instance for M on type +% [add-mixin T F M Cl] adds a constant being the mixin instance for M on type % T built from factory F -pred add-mixin i:term, i:factoryname, i:bool, i:mixinname, - o:list prop, o:list (pair id constant). -add-mixin T FGR MakeCanon MissingMixin [MixinSrcCl, BuilderDeclCl] CSL :- std.do! [ +pred add-mixin i:term, i:factoryname, i:mixinname, + o:prop, o:prop, o:constant. +add-mixin T FGR MissingMixin MixinSrcCl BuilderDeclCl C :- std.do! [ new_int N, % timestamp synthesis.assert!-infer-mixin T MissingMixin Bo, @@ -297,23 +325,15 @@ add-mixin T FGR MakeCanon MissingMixin [MixinSrcCl, BuilderDeclCl] CSL :- std.do (Name is {gref->modname FGR 2 "_"} ^"__to__" ^ {gref->modname MixinName 2 "_"}, if-verbose (coq.say {header} "declare mixin instance" Name), log.coq.env.add-const-noimplicits Name Bo Ty @transparent! C), - if (MakeCanon = tt, whd (global (const C)) [] (global (indc _)) _) - (std.do! [ - if-verbose (coq.say {header} "declare canonical mixin instance" C), - with-locality (log.coq.CS.declare-instance C), - CSL = [pr "_" C] - ]) (CSL = []), ]. -pred add-all-mixins i:term, i:factoryname, i:list mixinname, i:bool, - o:list prop, o:list (pair id constant). -add-all-mixins T FGR ML MakeCanon Clauses CSL :- std.do! [ - std.map ML (m\ o\ sigma ClL CSL\ - add-mixin T FGR MakeCanon m ClL CSL, o = pr ClL CSL) ClLxCSL_L, - std.unzip ClLxCSL_L ClLL CSLL, - std.flatten ClLL Clauses, - std.flatten CSLL CSL -]. +pred add-all-mixins i:term, i:factoryname, i:list mixinname, + o:list prop, o:list constant. +add-all-mixins _T _FGR [] [] []. +add-all-mixins T FGR [M|ML] [MixinSrcCL,BuilderDeclCL | CL] [C|CC] :- std.do! [ + add-mixin T FGR M MixinSrcCL BuilderDeclCL C, + add-all-mixins T FGR ML CL CC, +]. % [postulate-arity A Acc T TS] postulates section variables % corresponding to parameters in arity A. TS is T applied @@ -342,13 +362,19 @@ pred declare-canonical-instances-from-factory-and-local-builders declare-canonical-instances-from-factory-and-local-builders Factory T F _TheFactory FGR Clauses CSL :- std.do! [ synthesis.under-new-mixin-src-from-factory.do! T F (NewMixins\ std.do! [ - add-all-mixins T FGR NewMixins ff Clauses MCSL, + add-all-mixins T FGR NewMixins Clauses _TheMixins, ]), list-w-params_list {factory-provides Factory} ML, - Clauses => declare-all T {findall-classes-for ML} CCSL, - std.append MCSL CCSL CSL + Clauses => instance.declare-all T {findall-classes-for ML} CSL, ]. +pred make-mixin-canonical i:constant, o:option (pair id constant). +make-mixin-canonical C (some (pr "_" C)) :- whd (global (const C)) [] (global (indc _)) _, !, std.do! [ + if-verbose (coq.say {header} "declare canonical mixin instance" C), + with-locality (log.coq.CS.declare-instance C), +]. +make-mixin-canonical _ none. + % [declare-canonical-instances-from-factory T F] given a factory F % it uses all known builders to declare canonical instances of structures % on T @@ -362,14 +388,138 @@ declare-canonical-instances-from-factory Factory T F ClausesHas CSL :- std.do! [ synthesis.under-mixin-src-from-factory.do! T F [ synthesis.under-local-canonical-mixins-of.do! T [ list-w-params_list {factory-provides Factory} ML, - add-all-mixins T Factory ML tt Clauses MCSL, + add-all-mixins T Factory ML Clauses TheMixins, std.map-filter Clauses (mixin-src->has-mixin-instance ) ClausesHas, - ClausesHas => declare-all T {findall-classes-for ML} CCSL, % declare-all-on-type-constructor doesn't work here + ClausesHas => instance.declare-all T {findall-classes-for ML} CCSL, ] ], + std.map TheMixins make-mixin-canonical TheCanonicalMixins, + std.map-filter TheCanonicalMixins (x\r\x = some r) MCSL, std.append MCSL CCSL CSL ]. +% [declare-mixins-from-factory T F] given a factory F +% it uses all known builders to declare canonical instances of structures +% on T +pred declare-mixins-from-factory + i:factoryname, i:term, i:term, o:list mixinname, o:list constant. +declare-mixins-from-factory Factory T F ML TheMixins :- std.do! [ + % The order of the following two "under...do!" is crucial, + % priority must be given to canonical mixins + % as they are the ones which guarantee forgetful inheritance + % hence we add these clauses last. + synthesis.under-mixin-src-from-factory.do! T F [ + synthesis.under-local-canonical-mixins-of.do! T [ + list-w-params_list {factory-provides Factory} ML, + add-all-mixins T Factory ML _ TheMixins, + ] + ], +]. + +% [declare-structure-instance-from-mixins T ML MLI] given mixins ML and +% their implementation MLI declares all structure instances for T +pred declare-structure-instance-from-mixins i:term, i:list mixinname, i:list constant, o:list prop, o:list (pair id constant). +declare-structure-instance-from-mixins T ML TheMixins ClausesHas CL :- std.do! [ + % The order of the following two "under...do!" is crucial, + % priority must be given to canonical mixins + % as they are the ones which guarantee forgetful inheritance + % hence we add these clauses last. + synthesis.under-these-mixin-src.do! T ML TheMixins ClausesHas [ + synthesis.under-local-canonical-mixins-of.do! T [ + instance.declare-all T {findall-classes-for ML} CL, + ] + ], +]. + +pred close-section-if-has-params i:arity, i:id. +close-section-if-has-params (arity _) _ :- !. +close-section-if-has-params _ SectionName :- + if-verbose (coq.say {header} "closing instance section"), + log.coq.env.end-section-name SectionName. + +pred declare-regular-inst i:term, i:list mixinname, i:list constant, i:arity, i:id, + o:list prop, o:list (pair id constant). +declare-regular-inst TheType ML TheMixins TyWP SectionName ClausesHas CSL :- std.do![ + private.declare-structure-instance-from-mixins TheType ML TheMixins ClausesHas CCSL, + + % TODO: share between the two cases and put just after declare-mixins-from-factory + % since it talks about the unwrapped mixins + std.map TheMixins private.make-mixin-canonical TheCanonicalMixins, + std.map-filter TheCanonicalMixins (x\r\x = some r) MCSL, + std.append MCSL CCSL CSL, + + private.close-section-if-has-params TyWP SectionName, +]. + +pred declare-wrapper-inst i:term, i:list mixinname, i:list constant, i:arity, i:id, + o:list prop, o:list (pair id constant). +declare-wrapper-inst TheType ML TheMixins TyWP SectionName ClausesHas CSL :- std.do![ + coq.safe-dest-app TheType TheTypeKey _, + std.assert! (TheTypeKey = global TheTypeKeyGR) "The subject to be wrapped has no key", + private.close-section-if-has-params TyWP SectionName, + private.wrap-mixins TheTypeKeyGR ML TheMixins TheNewType WML TheWrappedMixins, + private.declare-structure-instance-from-mixins TheNewType WML TheWrappedMixins ClausesHas CSL, +]. + +pred derive-wrapper-instances i:term, i:mixinname, o:term, o:constant. +derive-wrapper-instances Instance WrapperMixin WrapperSubject C :- std.do! [ + + % K is the mixin constructor (Build) for WrapperMixin + factory-constructor WrapperMixin K, + factory-nparams WrapperMixin NParams, + + % We are only interested in the last parameter of the constructor + % type, which is the current instance + % (which is a Mixin instance on the new Subject). + % In monoid_enriched_cat.v, we are targeting the code + % + % HB.instance Definition funQ_hom_isMon := + % hom_isMon.Axioms_ _ _ funQ_isMon. + % which Coq can compute to stand for + % hom_isMon.Axioms_ Type funQ funQ_isMon. + % + % We compute the number of the underscores and we pass + % them as arguments followed by Instance. + coq.env.typeof K KTy, + coq.count-prods KTy KN, + KN0 is KN - 1, + coq.mk-n-holes KN0 Holes, + + std.append Holes [Instance] Args, + + % the body of the new wrapper instance + NewInstance = app[global K| Args], + + std.assert-ok! (coq.typecheck NewInstance Ty) "cannot wrap", + + coq.safe-dest-app Ty _Factory FArgs, + std.nth NParams FArgs WrapperSubject, + + Name is "wrapped__" ^ {std.any->string {new_int}}, + + log.coq.env.add-const-noimplicits Name NewInstance Ty @transparent! C, + ]. + +pred wrap-a-mixin i:gref, i:mixinname, i:constant, o:term, o:mixinname, o:constant. +wrap-a-mixin TheTypeKeyGR M TheMixin TheNewType WM TheWrappedMixin :- std.do! [ + std.findall (wrapper-mixin _ TheTypeKeyGR M) Wrappers, + std.assert! (not(Wrappers = [])) "wrap-a-mixin: no wrapper found", + if (Wrappers = [wrapper-mixin WM TheTypeKeyGR M]) + (TM = global (const TheMixin), + private.derive-wrapper-instances TM WM TheNewType TheWrappedMixin) + (coq.error "wrap-a-mixin: more than one way to wrap" TheTypeKeyGR "for" M), +]. + +pred wrap-mixins i:gref, i:list mixinname, i:list constant, + o:term, o:list mixinname, o:list constant. +wrap-mixins TheTypeKeyGR [ M | ML ] [ TheMixinInstance | TheMixins ] + TheNewType [ WM | WML ] [ TheWrappedMixin | TheWrappedMixins ] :- + wrap-a-mixin TheTypeKeyGR M TheMixinInstance TheNewType1 WM TheWrappedMixin, + std.assert! (TheNewType = TheNewType1) "wrapping leads to different subjects", + wrap-mixins TheTypeKeyGR ML TheMixins TheNewType WML TheWrappedMixins. +wrap-mixins _ [] [] _ [] []. + + % If you don't mention the factory in a builder, then Coq won't make % a lambda for it at section closing time. pred hack-section-discharging i:term, o:term. @@ -420,7 +570,7 @@ check-non-forgetful-inheritance T Factory :- std.do! [ if (coq.safe-dest-app T (global (const HdSym)) _, structure-key HdSym _ Super) ( coq.warning "HB" "HB.non-forgetful-inheritance" "non forgetful inheritance detected.\n" - "You have two solutions:" + "You have two solutions: " "1. (Best practice) Reorganize your hierarchy to make" {nice-gref->string Factory} "depend on" diff --git a/HB/pack.elpi b/HB/pack.elpi index b957db382..cdd8d1a3b 100644 --- a/HB/pack.elpi +++ b/HB/pack.elpi @@ -12,7 +12,6 @@ main Ty Args Instance :- std.do! [ std.assert! (Args = [trm TSkel|FactoriesSkel]) "HB.pack: not enough arguments", get-constructor Class KC, - get-constructor Structure KS, std.assert-ok! (d\ (coq.elaborate-ty-skeleton TSkel _ T d, d = ok) ; @@ -29,30 +28,67 @@ main Ty Args Instance :- std.do! [ (AllFactories = Factories) (AllFactories = Factories, Tkey = T), % it's a factory, won't add anything - private.synth-instance Params KC KS T Tkey AllFactories Instance, + private.synth-instance Params KC Tkey AllFactories ClassInstance, + + get-constructor Structure KS, + std.append Params [T, ClassInstance] InstanceArgs, + Instance = app[global KS | InstanceArgs] ]. +pred main-use-factories i:term, i:list argument, o:term. +main-use-factories Ty FactoriesSkel ClassInstance :- std.do! [ + std.assert! (not(var Ty)) "HB.from: the class cannot be unknown", + + factory? {unwind {whd Ty []}} (triple Class Params T), + + std.assert! (class-def (class Class _ _)) "HB.from: not a class", + + get-constructor Class KC, + + private.elab-factories FactoriesSkel T Factories, + + if (var T) (coq.error "HB.from: you must pass a type or at least one factory") true, + + if2 (T = app[global (const SortProj)|ProjParams], structure-key SortProj ClassProj _) + (AllFactories = [app[global (const ClassProj)|ProjParams] | Factories], Tkey = T) % already existing class on T + (def T _ _ Tkey) % we unfold letins if we can, they may hide constants with CS instances + (AllFactories = Factories) + (AllFactories = Factories, Tkey = T), % it's a factory, won't add anything + + private.try-synth-instance Params KC Tkey AllFactories ClassInstance, + +]. + + /* ------------------------------------------------------------------------- */ /* ----------------------------- private code ------------------------------ */ /* ------------------------------------------------------------------------- */ namespace private { -pred synth-instance i:list term, i:gref, i:gref, i:term, i:term, i:list term, o:term. -synth-instance Params KC KS T Tkey [Factory|Factories] Instance :- +pred synth-instance i:list term, i:gref, i:term, i:list term, o:term. +synth-instance Params KC Tkey [Factory|Factories] ClassInstance :- synthesis.under-new-mixin-src-from-factory.do! Tkey Factory (_\ - synth-instance Params KC KS T Tkey Factories Instance). -synth-instance Params KC KS T Tkey [] Instance :- coq.safe-dest-app Tkey (global _) _, !, + synth-instance Params KC Tkey Factories ClassInstance). +synth-instance Params KC Tkey [] ClassInstance :- coq.safe-dest-app Tkey (global _) _, !, synthesis.under-local-canonical-mixins-of.do! Tkey [ std.assert-ok! (synthesis.infer-all-args-let Params Tkey KC ClassInstance) "HB.pack: cannot infer the instance", - std.append Params [T, ClassInstance] InstanceArgs, - Instance = app[global KS | InstanceArgs] ]. -synth-instance Params KC KS T Tkey [] Instance :- std.do! [ +synth-instance Params KC Tkey [] ClassInstance :- std.do! [ std.assert-ok! (synthesis.infer-all-args-let Params Tkey KC ClassInstance) "HB.pack: cannot infer the instance", - std.append Params [T, ClassInstance] InstanceArgs, - Instance = app[global KS | InstanceArgs] +]. + +pred try-synth-instance i:list term, i:gref, i:term, i:list term, o:term. +try-synth-instance Params KC Tkey [Factory|Factories] ClassInstance :- + synthesis.under-new-mixin-src-from-factory.do! Tkey Factory (_\ + try-synth-instance Params KC Tkey Factories ClassInstance). +try-synth-instance Params KC Tkey [] ClassInstance :- coq.safe-dest-app Tkey (global _) _, !, + synthesis.under-local-canonical-mixins-of.do! Tkey [ + synthesis.try-infer-all-args-let Params Tkey KC ClassInstance, +]. +try-synth-instance Params KC Tkey [] ClassInstance :- std.do! [ + synthesis.try-infer-all-args-let Params Tkey KC ClassInstance, ]. pred elab-factories i:list argument, i:term, o:list term. diff --git a/HB/status.elpi b/HB/status.elpi index e6bf3684e..ab857a82f 100644 --- a/HB/status.elpi +++ b/HB/status.elpi @@ -28,6 +28,13 @@ print-hierarchy :- std.do! [ std.forall BDL private.pp-builder-decl ), + std.findall (wrapper-mixin _ _ _) WL, + if (WL = []) true ( + coq.say "", + coq.say "--------------------- Wrappers ----------------------", + std.forall WL private.pp-wrapper + ), + std.findall (current-mode BF_) BFL, if (BFL = []) true ( coq.say "", @@ -76,6 +83,10 @@ pp-builder-decl (builder-decl (builder N F M GR)) :- coq.say "builder" GR "with serial number" N "will build mixin" M "from factory" F. +pred pp-wrapper i:prop. +pp-wrapper (wrapper-mixin W O M) :- + coq.say "wrapper" W "for mixin" M "for lifter" O. + pred pp-current-mode i:prop. pp-current-mode (current-mode (builder-from TheType TheFactory GRF Mod)) :- coq.say "The current key is" TheType "with factory" TheFactory diff --git a/HB/structure.elpi b/HB/structure.elpi index be549496a..98733af3e 100644 --- a/HB/structure.elpi +++ b/HB/structure.elpi @@ -7,12 +7,21 @@ namespace structure { % cons p1\ cons p2\ nil t\ [triple f1 [p1] t,triple f2 [p1, {{p1 * p2}}] t] pred declare i:string, i:term, i:sort. pred declare i:string, i:term, i:universe. -declare Module BSkel Sort :- std.do! [ +declare Module BSkel Sort :- + private.declare-wrappers BSkel WrapperClauses, % move to factory.elpi + + WrapperClauses => std.do! [ + disable-id-phant BSkel BSkelNoId, - std.assert-ok! (coq.elaborate-skeleton BSkelNoId _ BNoId) "illtyped structure definition", + failsafe-structure-inference BSkelNoId BSkelNoIdX, + %coq.say {coq.term->string BSkelNoIdX} BSkelNoIdX, + std.assert-ok! (coq.elaborate-skeleton BSkelNoIdX _ BNoId) "illtyped structure definition", re-enable-id-phant BNoId B, - private.sigT->list-w-params B GRFSwP ClosureCheck, + private.sigT->list-w-params B GRFSwP_or_ThingtoBeWrapped ClosureCheck, + % do some work to go back to factories on a single subject + private.lift-to-the-subject GRFSwP_or_ThingtoBeWrapped GRFSwP, + factories-provide GRFSwP PMLwP, list-w-params.flatten-map GRFSwP gref-deps RMLwP, % TODO: extract code from factories-provide @@ -127,7 +136,8 @@ declare Module BSkel Sort :- std.do! [ std.flatten [ Factories, [ClassAlias], [is-structure Structure], NewJoins, [class-def CurrentClass], GRDepsClauses, - [gref-deps GRPack MLwP], MixinMems, [StructKeyClause] + [gref-deps GRPack MLwP], MixinMems, [StructKeyClause], + WrapperClauses ] NewClauses, acc-clauses current NewClauses, @@ -176,6 +186,12 @@ declare Module BSkel Sort :- std.do! [ log.coq.env.end-module-name ElpiOperationModName ElpiOperations, export.module ElpiOperationModName ElpiOperations, + % we need to assert locally the clauses in EX + EX => std.forall ML private.reexport-wrapper-as-instance, + + %hack + hack, + if-verbose (coq.say {header} "abbreviation factory-by-classname"), NewClauses => factory.declare-abbrev Module (factory.by-classname ClassName), @@ -187,6 +203,11 @@ declare Module BSkel Sort :- std.do! [ % NewClauses => instance.saturate-instances, ]. +pred hack. +hack :- coq.next-synterp-action (begin-section X), coq.env.begin-section X, hack. +hack :- coq.next-synterp-action end-section, coq.env.end-section, hack. +hack. + /* ------------------------------------------------------------------------- */ /* ----------------------------- private code ------------------------------ */ /* ------------------------------------------------------------------------- */ @@ -204,7 +225,6 @@ clean-op-ty [exported-op _ Po C|Ops] S T1 T2 :- gref-deps (const Po) MLwP, w-params.nparams MLwP NParams, std.length {list-w-params_list MLwP} NMixins, - (pi L L1 L2 Params Rest PoArgs\ copy (app [global (const Po)| L]) (app [global (const C) | L2]) :- std.split-at NParams L Params [_|Rest], @@ -610,16 +630,53 @@ if-coverage-not-good-error.one MS M :- mixin-first-class M C, !, "which contains at most" {std.map {coq.gref.set.elements {coq.gref.set.inter CMS MS}} nice-gref->string}). if-coverage-not-good-error.one _ _. % new class is the first covering M -pred product->triples i:term, o:list (w-args factoryname), o:bool. -product->triples {{ lib:hb.prod lp:A lp:B }} L ClosureCheck :- !, - product->triples B GRB ClosureCheck, - product->triples A GRA _, - std.append GRA GRB L. -product->triples {{ True }} [] tt :- !. -product->triples {{ False }} [] ff :- !. -product->triples A [GR] tt :- std.assert! (factory? A GR) "A structure can only mention known factories". +% 1. write a predicate to recognize factory applied to op, maybe under a forall prefix +% factory-on-some-structure-op? +% 2. change the type of product->triples and sigT->list-w-params to +% return a list-w-params of either a factoryname or a thing-to-be-wrapper +% (eg mixin to be wrapped, operation) +% 3. the caller of sigT->list-w-params has to pre-process the list +% and generate wrapper mixins for each thing-to-be-wrapper and replace +% in the list the thing-to-be-wrapper with the wrapper mixin +% - one needs to find to which structure the operation belongs and +% use that structure to synthesize the type of the wrapper, eg +% hom belongs to Quiver, hence hom_isMon takes a "T of Quiver T" + +% checks if the term is forall A B C, Factory ... (Op A B C) ... +pred factory-on-some-structure-op? i:term, i:list term, o:gref, o:gref. +factory-on-some-structure-op? (prod N Ty Bo) VS F OP :- + @pi-decl N Ty x\ + factory-on-some-structure-op? (Bo x) [x|VS] F OP. +factory-on-some-structure-op? T VS F (const OP) :- + factory? T (triple F _ Subject), + coq.safe-dest-app Subject (global (const OP)) Args, + exported-op _ _ OP, + std.appendR _ {std.rev VS} Args. +factory-on-some-structure-op? T VS F GR :- std.do! [ + factory? T (triple F _ Subject), + coq.safe-dest-app Subject (global GR) Args, + tag GR _ _, + std.appendR _ {std.rev VS} Args, +]. + +kind factory-on-subject type. +type factory-on-the-type w-args factoryname -> factory-on-subject. +type factory-on-subject-lifter term -> factoryname -> gref -> factory-on-subject. -pred sigT->list-w-params i:term, o:list-w-params factoryname, o:bool. +pred product->triples i:term, i:term, o:list factory-on-subject, o:bool. +product->triples {{ lib:hb.prod lp:A lp:B }} T L ClosureCheck :- !, + product->triples B T GRB ClosureCheck, + product->triples A T GRA _, + std.append GRA GRB L. +product->triples {{ True }} _ [] tt :- !. +product->triples {{ False }} _ [] ff :- !. +product->triples A T [factory-on-the-type F] tt :- (factory? A F), (F = triple _ _ T), !. +product->triples A _ [factory-on-subject-lifter A F OP] tt :- factory-on-some-structure-op? A [] F OP, !. +product->triples A T _ _ :- + coq.error "HB: expecting a factory on" {coq.term->string T} + "or a factory on a structure operation or tag. Got:" {coq.term->string A}. + +pred sigT->list-w-params i:term, o:w-params (list factory-on-subject), o:bool. sigT->list-w-params (fun N T B) L C :- coq.name->id N ID, % TODO: we should read the ID from the definition type which is an arity containing ids L = w-params.cons ID T Rest, @@ -629,6 +686,224 @@ sigT->list-w-params {{ lib:@hb.sigT _ lp:{{ fun N Ty B }} }} L C :- coq.name->id N ID, % TODO: we should read the ID from the definition type which is an arity containing ids L = w-params.nil ID Ty Rest, @pi-decl N Ty t\ - product->triples (B t) (Rest t) C. + product->triples (B t) t (Rest t) C. + +%TODO expand factories in lift +pred lift-to-the-subject i:w-params (list factory-on-subject), o:list-w-params factoryname. +lift-to-the-subject (w-params.cons ID T Rest) (w-params.cons ID T Rest1) :- + @pi-parameter ID T x\ + lift-to-the-subject (Rest x) (Rest1 x). +lift-to-the-subject (w-params.nil ID T Rest) (w-params.nil ID T Rest1) :- + @pi-parameter ID T x\ + lift-to-the-subject.aux (Rest x) x (Rest1 x). +lift-to-the-subject.aux [] _ []. +lift-to-the-subject.aux [factory-on-the-type F|Rest] T [F|Rest1] :- + lift-to-the-subject.aux Rest T Rest1. +lift-to-the-subject.aux [factory-on-subject-lifter _ F OP|Rest] T [WF|Rest1] :- + wrapper-mixin Wrapper OP F, !, std.do! [ + factory-nparams Wrapper NParams, + coq.mk-app {coq.env.global Wrapper} {std.append {coq.mk-n-holes NParams} [T]} W, + factory? W WF, + lift-to-the-subject.aux Rest T Rest1, +]. +lift-to-the-subject.aux [factory-on-subject-lifter Expr _ _|_] _ _ :- + coq.error "NYI: automatic wrapping for" {coq.term->string Expr}. + +pred declare-wrappers i:term, o:list prop. +declare-wrappers B C :- std.do! [ + private.sigT->list-w-params B X _, + declare-wrappers.filter-lifted X Wrappers, + w-params.map Wrappers (_\_\std.flatten) Wrappers1, + distribute-w-params Wrappers1 WrappersWP, + std.fold WrappersWP [] declare-wrapper C, +]. +pred declare-wrappers.filter-lifted i:w-params (list factory-on-subject), o:w-params (list (list (pair gref (w-args mixinname)))). +declare-wrappers.filter-lifted (w-params.cons ID T F) (w-params.cons ID T F1) :- + @pi-parameter ID T x\ declare-wrappers.filter-lifted (F x) (F1 x). +declare-wrappers.filter-lifted (w-params.nil ID T F) (w-params.nil ID T F1) :- + @pi-parameter ID T x\ declare-wrappers.filter-lifted.aux (F x) (F1 x). +declare-wrappers.filter-lifted.aux [factory-on-the-type _|XS] R :- declare-wrappers.filter-lifted.aux XS R. +declare-wrappers.filter-lifted.aux [factory-on-subject-lifter T F G|XS] [WL|R] :- + factory? T (triple _ Params S), + factory-provides F MLwP, + apply-w-params MLwP Params S Triples, + std.map-filter Triples (declare-wrappers.filter-new G) WL, + declare-wrappers.filter-lifted.aux XS R. +declare-wrappers.filter-lifted.aux [] []. + +pred declare-wrappers.filter-new i:gref, i:w-args mixinname, o:pair gref (w-args mixinname). +declare-wrappers.filter-new G (triple F _ _ as T) (pr G T) :- not (wrapper-mixin _ G F). + +pred wrap-deps i:gref, i:mixins, o:mixins. +wrap-deps OP (w-params.cons ID T F) (w-params.cons ID T F1) :- + @pi-parameter ID T x\ wrap-deps OP (F x) (F1 x). +wrap-deps OP (w-params.nil ID T F) (w-params.nil ID T F1) :- + @pi-parameter ID T x\ wrap-deps.mixins OP (F x) (F1 x). + +pred wrap-deps.mixins i:gref, i:list (w-args mixinname), o:list (w-args mixinname). +wrap-deps.mixins _ [] []. +wrap-deps.mixins OP [triple M P X|ML] [triple WM P X|ML1] :- + std.assert! (wrapper-mixin WM OP M) "no wrapper for the lifter on a dep", + wrap-deps.mixins OP ML ML1. + +pred declare-wrapper i:w-params (pair gref (w-args mixinname)), i:list prop, o:list prop. +declare-wrapper F C0 C :- C0 => std.do! [ + %coq.say "Missing" F, + missing-wrapper->record F RSkel OP M, + %coq.say "Wrapper skel" F "=" RSkel, + %disable-id-phant-indt-decl RSkel RSkelNoId, + %std.assert-ok! (coq.elaborate-indt-decl-skeleton RSkelNoId RDeclNoId) "illtyped wrapper", + %re-enable-id-phant-indt-decl RDeclNoId RDecl, + %coq.say "Record wrapper" RDecl, + gref-deps M MDeps, + wrap-deps OP MDeps WrappedDeps, + ((pi X Y L\ copy X Y :- var X _ L, prune Y L) => copy-indt-decl RSkel RSkel'), std.spy(expand-structures RSkel' WrappedDeps W'), + %coq.say "Expanded record wrapper" W', + %std.assert-ok! (coq.typecheck-indt-decl W) "illtyped wrapper record", + coq.say "Wrapper for" OP "and" M "is" W', + std.assert-ok! (coq.elaborate-indt-decl-skeleton W' W) "illtyped wrapper record", + %coq.say W, + log.coq.env.add-indt W R, + coq.env.indt R tt _ _ _ [K] _, + GRK = indc K, + GR = indt R, + + coq.gref->id GR Name, + + wrapper-deps F W MLwP, + %coq.say "W deps" F "=" MLwP, + + w-params.nparams MLwP NParams, + factory.private.build-deps-for-projections R MLwP GRDepsClausesProjs, + GRDepsClauses = [ gref-deps GR MLwP, gref-deps (indc K) MLwP | GRDepsClausesProjs], + + GRDepsClauses => phant.of-gref ff GRK [] PhGRK, + GRDepsClauses => phant.add-abbreviation {calc (Name ^ "_Build")} PhGRK BuildConst BuildAbbrev, + GRDepsClauses => phant.of-gref ff GR [] PhTerm, + GRDepsClauses => phant.add-abbreviation {calc (Name ^ "_axiom")} PhTerm PhC Abbrv, + + FRClauses = [ + phant-abbrev GRK (const BuildConst) BuildAbbrev, + phant-abbrev GR (const PhC) Abbrv, + ], + + GRDepsClauses => FRClauses => factory.private.declare-id-builder GR IdBuilderClause, + + std.flatten [ C0, + [ wrapper-mixin GR OP M, + factory-constructor GR GRK, + factory-nparams GR NParams, + IdBuilderClause], + FRClauses, + GRDepsClauses, + ] C, + %factory-builder-nparams BuildConst NParams, + coq.say "Wrapper DONE" F, +]. + +pred missing-wrapper->record i:w-params (pair gref (w-args mixinname)), o:indt-decl, o:gref, o:mixinname. +missing-wrapper->record (w-params.cons ID T F) (parameter ID explicit T F1) OP M:- + @pi-parameter ID T x\ missing-wrapper->record (F x) (F1 x) OP M. +missing-wrapper->record (w-params.nil ID T F) (parameter ID explicit T F1) OP M:- + @pi-parameter ID T x\ missing-wrapper->record.body (F x) (F1 x) OP M. + +pred unfold-phant i:term, o:term. +unfold-phant (app [global (const C)|A]) R :- + coq.env.const C (some B) _, + unwind {hd-beta B A} R. + +pred missing-wrapper->record.body i:pair gref (w-args mixinname), o:indt-decl, o:gref, o:mixinname. +missing-wrapper->record.body (pr OP (triple M Params Subject)) + (record Name _ Bname (field [] Fname T (x\end-record))) OP M :- std.do! [ + coq.mk-app {coq.env.global M} {std.append Params [Subject]} T, + + Name is "wrapper_" ^ {std.any->string {new_int}} ^ "_" ^ {coq.gref->id OP} ^ "_" ^ {nice-gref->string M}, + Fname is Name ^ "_private", + Bname is Name ^ "_build", +]. + +pred wrapper-deps i:w-params (pair gref (w-args gref)), i:indt-decl, o:mixins. +wrapper-deps (w-params.cons _ _ F) (parameter ID explicit T F1) (w-params.cons ID T ML) :- + @pi-parameter ID T x\ wrapper-deps (F x) (F1 x) (ML x). +wrapper-deps (w-params.nil _ _ _) (parameter ID explicit T F1) (w-params.nil ID T ML) :- + @pi-parameter ID T x\ wrapper-deps.aux (F1 x) x (ML x). +wrapper-deps.aux (parameter ID explicit T F1) X [triple M Params X|ML] :- + coq.safe-dest-app T Mixin ParamsXStuff, + coq.env.global M Mixin, + std.appendR Params [X|_] ParamsXStuff, + @pi-parameter ID T x\ wrapper-deps.aux (F1 x) X ML. +wrapper-deps.aux (record _ _ _ _) _ []. + +pred expand-structures i:indt-decl, i:mixins, o:indt-decl. +expand-structures (parameter ID I T ((s\record _ _ _ (field _ _ (X s) _\end-record)) as R)) Deps (parameter ID I _ R1) :- !, std.spy-do! [ + (@pi-decl `TheType` T x\ std.assert-ok! (coq.typecheck (X x) (Ty_ x)) "illtyped subject"), + coq.safe-dest-app T (global GR) Args, is-structure GR, class-def (class C GR ML), + coq.mk-n-holes {w-params.nparams Deps} Holes, + get-constructor C K, + get-constructor GR SK, + coq.mk-app (global SK) Args SKArgs, + (@pi-decl `TheType` {{ Type }} x\ % TYPE is wrong + apply-w-params ML Args x (F x), + apply-w-params Deps Holes x (DepsX x), + %toposort-mixins {std.append (F x) (DepsX x)} (MoreParams x), + expand-structures.aux (F x) (DepsX x) [] {coq.mk-app SKArgs [x]} K Args x R (R1 x)), +]. +expand-structures(parameter ID I T F) Deps (parameter ID I T F1) :- + @pi-parameter ID T x\ expand-structures (F x) Deps (F1 x). +expand-structures.aux [triple M PS X|MS] D ACC Pack K KA Subj R (parameter "m" explicit Ty R1) :- std.do! [ + synthesis.infer-all-gref-deps PS X M Ty, + (@pi-decl `m` Ty m\ mixin-src X M m => + expand-structures.aux MS D ACC Pack K KA Subj R (R1 m)), +]. +expand-structures.aux [] [triple M PS X|D] ACC Pack K KA Subj R (parameter "m" explicit Ty R1) :- std.do! [ + synthesis.infer-all-gref-deps PS X M Ty, + coq.safe-dest-app Ty _ Args, + M = indt I, + std.assert! (coq.env.projections I [some Priv]) "wrapper with no projection", + (@pi-decl `m` Ty m\ sigma PM\ + coq.mk-app (app [{coq.env.global (const Priv)}|Args]) [m] PM, + mixin-src X M m => + expand-structures.aux [] D [PM|ACC] Pack K KA Subj R (R1 m)), +]. +expand-structures.aux [] [] WrappedDepsRev Pack K KA Subj R R2 :- std.do! [ + synthesis.infer-all-gref-deps KA Subj K Class, + R1 = R {coq.mk-app Pack [Class]}, + R1 = record N S NK (field FA FN T _\end-record), + R2 = record N S NK (field FA FN T1 _\end-record), + factory? T (triple F Params LiftedSubject), + %std.assert! (std.forall Deps var) "wrapper: deps should be inferred, not given", + %CONVOLUTED + std.rev WrappedDepsRev WrappedDeps, + coq.mk-app (app [global F|Params]) [LiftedSubject|WrappedDeps] T1, +]. + +% M is the gref of the wrapper mixin. +% C gets now instantiated to the projection, i.e. hom_isMon_private. +% we need to count the parameters, we can get that from the type. +% we then can construct the instance, using +% instance.declare-const (notably used in the API, i.e. in structures.v, +% HB.instance) +pred reexport-wrapper-as-instance i:mixinname. +reexport-wrapper-as-instance M :- wrapper-mixin M _ _, !, std.do! [ + + % need the body of the wrapper projection type + exported-op M _ C, + B = (global (const C)), + coq.env.typeof (const C) Ty, + coq.count-prods Ty N0, + coq.term->arity Ty N0 Arity, + + % need a recognisable valid idenfier for the derived instance + Str0 is "Op_isMx" ^ "__" ^ {std.any->string {new_int}}, + std.string.concat "__" [Str0, "ELIM"] Str, + + get-option "wrapper" ff => instance.declare-const Str B Arity _ + ]. +reexport-wrapper-as-instance _ :- + std.assert! (coq.next-synterp-action (begin-section SectionName)) "synterp code did not open section", + coq.env.begin-section SectionName, + std.assert! (coq.next-synterp-action (end-section)) "synterp code did not close section", + coq.env.end-section. + }} diff --git a/Makefile b/Makefile index 14cfc4a9a..499b18691 100644 --- a/Makefile +++ b/Makefile @@ -138,7 +138,7 @@ sub-%: __always__ endif # Make of individual .vo --------------------------------------------- -structures.vo : %.vo: __always__ Makefile.coq +$(addsuffix o,structures.v $(wildcard theories/*.v)): %.vo: __always__ Makefile.coq +$(COQMAKE) $@ $(addsuffix o,$(wildcard examples/*.v examples/*/*.v tests/*.v tests/unit/*.v)): __always__ config build Makefile.test-suite.coq diff --git a/Makefile.coq.local b/Makefile.coq.local index fdbf88499..574d21940 100644 --- a/Makefile.coq.local +++ b/Makefile.coq.local @@ -1,5 +1,5 @@ # Coq does not know about Elpi Accumulate File, so we declare the dependency here -structures.vo : $(wildcard HB/*.elpi HB/common/*.elpi) +theories/structures.vo : $(wildcard HB/*.elpi HB/common/*.elpi) clean:: $(SHOW)'CLEAN *.hb *.hb.old' diff --git a/Makefile.test-suite.coq.local b/Makefile.test-suite.coq.local index 2b1a6ac59..605b5634e 100644 --- a/Makefile.test-suite.coq.local +++ b/Makefile.test-suite.coq.local @@ -7,7 +7,7 @@ output_for=`\ fi` DIFF=\ - @if [ -z "$$COQ_ELPI_ATTRIBUTES" ]; then \ + if [ -z "$$COQ_ELPI_ATTRIBUTES" ]; then \ echo OUTPUT DIFF $(1);\ $(COQTOP) $(COQFLAGS) $(COQLIBS) -topfile $(1) \ < $(1) 2>/dev/null \ diff --git a/_CoqProject b/_CoqProject index 057e90014..6fd1beebb 100644 --- a/_CoqProject +++ b/_CoqProject @@ -1,7 +1,12 @@ -structures.v +theories/structures.v +theories/cat.v +theories/encatD.v +theories/encatI.v +theories/encatH.v -arg -w -arg -elpi.accumulate-syntax -arg -w -arg +elpi.typecheck --Q . HB +-arg -w -arg -redundant-canonical-projection -R tests HB.tests --R examples HB.examples \ No newline at end of file +-R examples HB.examples +-R theories HB diff --git a/_CoqProject.test-suite b/_CoqProject.test-suite index d60c9bb6c..9c7e78e57 100644 --- a/_CoqProject.test-suite +++ b/_CoqProject.test-suite @@ -53,7 +53,7 @@ examples/Coq2020_material/CoqWS_abstract.v examples/Coq2020_material/CoqWS_expansion/withHB.v examples/Coq2020_material/CoqWS_expansion/withoutHB.v -# examples/cat/cat.v +tests/enriched_cat_case6.v tests/type_of_exported_ops.v tests/duplicate_structure.v @@ -94,8 +94,10 @@ tests/unit/mk_src_map.v tests/unit/close_hole_term.v tests/unit/struct.v tests/factory_when_notation.v +tests/monoid_enriched_cat.v +tests/tag_wrap.v -R tests HB.tests -R examples HB.examples --Q . HB \ No newline at end of file +-R theories HB \ No newline at end of file diff --git a/tests/about.v b/tests/about.v index a8971ab2b..0e114d234 100644 --- a/tests/about.v +++ b/tests/about.v @@ -46,7 +46,7 @@ HB.about hierarchy_5_Ring_class__to__hierarchy_5_SemiRing_class. HB.about hierarchy_5_Ring__to__hierarchy_5_SemiRing. (* builder *) -HB.about Builders_40.hierarchy_5_Ring_of_AddAG__to__hierarchy_5_BiNearRing_of_AddMonoid. +HB.about Builders_36.hierarchy_5_Ring_of_AddAG__to__hierarchy_5_BiNearRing_of_AddMonoid. HB.locate BinNums_Z__canonical__hierarchy_5_AddAG. diff --git a/tests/cmonoid_enriched_cat.v b/tests/cmonoid_enriched_cat.v new file mode 100644 index 000000000..fa18b328e --- /dev/null +++ b/tests/cmonoid_enriched_cat.v @@ -0,0 +1,698 @@ +From HB Require Import structures. +From Coq Require Import ssreflect ssrfun. + +(** Quiver *) + +HB.mixin Record isQuiver Obj := { hom : Obj -> Obj -> Type }. + +HB.structure Definition Quiver := { Obj of isQuiver Obj }. + + +(*************************************** OTHER MIXINS *************) +(******************************* Exploring different alternatives *) + +(************* 1) Monolithic definition; not used *) +HB.mixin Record isMon A := { + zero : A; + add : A -> A -> A; + addrA : associative add; + add0r : left_id zero add; + addr0 : right_id zero add; + }. + +(***** using the monolithic approach to extend monoids with + idempotence and commutativity can be cumbersome *) + +HB.mixin Record isIMonB A := { + zero : A; + add : A -> A -> A; + addrA : associative add; + add0r : left_id zero add; + addr0 : right_id zero add; + addI : idempotent add; +}. + +HB.mixin Record isCMonB A := { + zero : A; + add : A -> A -> A; + addrA : associative add; + add0r : left_id zero add; + addr0 : right_id zero add; + addC : commutative add; +}. + + +(**************** 2) Small mixins (problem with sharing); not used *) + +HB.mixin Record isIAlg A := { + iadd : A -> A -> A; + iaddI : idempotent iadd; + }. + +HB.mixin Record isCAlg A := { + cadd : A -> A -> A; + caddrC : commutative cadd; + }. + + +(***************** 3) Sharing my equalities: vanilla Coq (no HB) *) + +Record isMon0 A := { + zero0 : A; + add0 : A -> A -> A; + addrA0 : associative add0; + add0r0 : left_id zero0 add0; + addr00 : right_id zero0 add0; + }. + +Record isIAlg0 A := { + iadd0 : A -> A -> A; + iaddI0 : idempotent iadd0; + }. + +(* this would require additional support *) +Record isIMon0 A := { is_mon0 : isMon0 A; + is_ialg0 : isIAlg0 A; + mon_ialg_ch0 : add0 _ is_mon0 = iadd0 _ is_ialg0 ; + }. + +(*** The analogous of vanilla does not work in HB *) + +Fail HB.mixin Record isIMonM A := { is_mon : isMon A; + is_ialg : isIAlg A; + mon_ialg_ch : add _ is_mon = iadd _ is_ialg ; + }. + +Fail HB.mixin Record isIMonS A := { is_mon : Monoid A; + is_ialg : IAlgebra A; + mon_ialg_ch : add _ is_mon = iadd _ is_ialg ; + }. + + +(************************* 4) Operator-sharing small mixins *) + +(*********** 4.1) mixins with single dependent pair parameter, using + sigma types; complicates things; not used *) + +HB.mixin Record isOpMon1 (S: sigT (fun A => A -> A -> A)) := { + zero : projT1 S; + addrA : associative (projT2 S); + add0r : left_id zero (projT2 S); + addr0 : right_id zero (projT2 S); + }. + +HB.mixin Record isOpIAlg1 (S: sigT (fun A => A -> A -> A)) := { + addI : idempotent (projT2 S); + }. + + +(*********** 4.2) USED: mixins with multiple parameters instead of a + single dependent pair; possibly less general, but works well + with the running example (notice that the subject here could be + an operator, i.e. Add) *) + +(**** Base Mixins *) + +(* associative algebra *) +HB.mixin Record isOpAAlg2 A (Add: A -> A -> A) := { + addA : associative Add; + }. + +HB.mixin Record isOpAAlgebra2 A := { add: A -> A -> A; + is_op_aalg : isOpAAlg2 A add }. + +(* algebra with zero *) +HB.mixin Record isOpZAlg2 A (Add: A -> A -> A) (Zero: A) := { + add0r : left_id Zero Add; + addr0 : right_id Zero Add; + }. + +HB.mixin Record isOpZAlgebra2 A := { add: A -> A -> A; + zero: A; + is_op_zalg : isOpZAlg2 A add zero }. + +(* idempotent algebra *) +HB.mixin Record isOpIAlg2 A (Add: A -> A -> A) := { + addI : idempotent Add; + }. + +HB.mixin Record isOpIAlgebra2 A := { add: A -> A -> A; + is_op_ialg : isOpIAlg2 A add }. + +(* commutative algebra *) +HB.mixin Record isOpCAlg2 A (Add: A -> A -> A) := { + addC : commutative Add; + }. + +HB.mixin Record isOpCAlgebra2 A := { add: A -> A -> A; + is_op_calg : isOpCAlg2 A add }. + +(**** Complex Mixins *) + +(* monoid *) +HB.mixin Record isOpMon2 A (Add: A -> A -> A) (Zero: A) := { + is_op_zalg : isOpZAlg2 A Add Zero ; + is_op_aalg : isOpAAlg2 A Add ; + }. + +HB.mixin Record isOpMonoid2 A := { add: A -> A -> A; + zero: A; + is_op_mon : isOpMon2 A add zero }. + +(* idempotent monoid *) +HB.mixin Record isOpIMon2 A (Add: A -> A -> A) (Zero: A) := { + is_op_mon : isOpMon2 A Add Zero ; + is_op_ialg : isOpIAlg2 A Add ; + }. + +HB.mixin Record isOpIMonoid2 A := { add: A -> A -> A; + zero: A; + is_op_imon : isOpIMon2 A add zero }. + +(* commutative monoid *) +HB.mixin Record isOpCMon2 A (Add: A -> A -> A) (Zero: A) := { + is_op_mon : isOpMon2 A Add Zero ; + is_op_calg : isOpCAlg2 A Add ; + }. + +HB.mixin Record isOpCMonoid2 A := { add: A -> A -> A; + zero: A; + is_op_imon : isOpCMon2 A add zero }. + +(* commutative idempotent algebra *) +HB.mixin Record isOpCIAlg2 A (Add: A -> A -> A) := { + is_op_ialg : isOpIAlg2 A Add ; + is_op_calg : isOpCAlg2 A Add ; + }. + +HB.mixin Record isOpCIAlgebra2 A := { add: A -> A -> A; + is_op_cialg : isOpCIAlg2 A add }. + +(* idempotent commutative algebra *) +HB.mixin Record isOpICAlg2 A (Add: A -> A -> A) := { + is_op_calg : isOpCAlg2 A Add ; + is_op_ialg : isOpIAlg2 A Add ; + }. + +HB.mixin Record isOpICAlgebra2 A := { add: A -> A -> A; + is_op_calg : isOpICAlg2 A add }. + +(* associative commutative idempotent algebra *) +HB.mixin Record isOpACIAlg2 A (Add: A -> A -> A) := { + is_op_ialg : isOpIAlg2 A Add ; + is_op_calg : isOpCAlg2 A Add ; + is_op_aalg : isOpAAlg2 A Add ; + }. + +HB.mixin Record isOpACIAlgebra2 A := { add: A -> A -> A; + is_op_acialg : isOpACIAlg2 A add }. + +(* commutative idempotent monoid *) +HB.mixin Record isOpCIMon2 A (Add: A -> A -> A) (Zero: A) := { + is_op_mon : isOpIMon2 A Add Zero ; + is_op_calg : isOpCAlg2 A Add ; + }. + +HB.mixin Record isOpCIMonoid2 A := { add: A -> A -> A; + zero: A; + is_op_cimon : isOpCIMon2 A add zero }. + +(* idempotent commutative monoid *) +HB.mixin Record isOpICMon2 A (Add: A -> A -> A) (Zero: A) := { + is_op_mon : isOpCMon2 A Add Zero ; + is_op_calg : isOpIAlg2 A Add ; + }. + +HB.mixin Record isOpICMonoid2 A := { add: A -> A -> A; + zero: A; + is_op_cimon : isOpICMon2 A add zero }. + + +(************************************** STRUCTURES ***********************) + +(********************* NOT USED *) + +(** Base structures *) + +HB.structure Definition Monoid := { A of isMon A }. + +HB.structure Definition CAlgebra := { A of isCAlg A }. + +HB.structure Definition IAlgebra := { A of isIAlg A }. + +(** Complex structures *) + +HB.structure Definition OpMonoid1 := { C of isOpMon1 C }. + +HB.structure Definition OpIAlgebra1 := { C of isOpIAlg1 C }. + +HB.mixin Record isOpIMon1 A of OpMonoid1 A & OpIAlgebra1 A. + +(*******************************************************************) + +(********************** USED: based on operator-sharing, + simple-parameters mixins *) + +(** Base structures *) + +HB.structure Definition OpAAlgebra2 := { A of isOpAAlgebra2 A }. + +HB.structure Definition OpZAlgebra2 := { A of isOpZAlgebra2 A }. + +HB.structure Definition OpIAlgebra2 := { A of isOpIAlgebra2 A }. + +HB.structure Definition OpCAlgebra2 := { A of isOpCAlgebra2 A }. + +(** Complex structures *) + +HB.structure Definition OpMonoid2 := { A of isOpMonoid2 A }. + +HB.structure Definition OpIMonoid2 := { A of isOpIMonoid2 A }. + +HB.structure Definition OpCMonoid2 := { A of isOpCMonoid2 A }. + +HB.structure Definition OpCIAlgebra2 := { A of isOpCIAlgebra2 A }. + +HB.structure Definition OpICAlgebra2 := { A of isOpICAlgebra2 A }. + +HB.structure Definition OpACIAlgebra2 := { A of isOpACIAlgebra2 A }. + +HB.structure Definition OpCIMonoid2 := { A of isOpCIMonoid2 A }. + +HB.structure Definition OpICMonoid2 := { A of isOpICMonoid2 A }. + + +(******************************************** WRAPPERS *******) + +(** Base wrappers *) + +#[wrapper] +HB.mixin Record hom_isAAlg T of Quiver T := + { hom_isAAlg_private : forall A B, isOpAAlgebra2 (@hom T A B) }. + +#[wrapper] +HB.mixin Record hom_isZAlg T of Quiver T := + { hom_isZAlg_private : forall A B, isOpZAlgebra2 (@hom T A B) }. + +#[wrapper] +HB.mixin Record hom_isIAlg T of Quiver T := + { hom_isIAlg_private : forall A B, isOpIAlgebra2 (@hom T A B) }. + +#[wrapper] +HB.mixin Record hom_isCAlg T of Quiver T := + { hom_isCAlg_private : forall A B, isOpCAlgebra2 (@hom T A B) }. + + +(** Complex wrappers *) + +#[wrapper] +HB.mixin Record hom_isMon T of Quiver T := + { hom_isMon_private : forall A B, isOpMonoid2 (@hom T A B) }. + +#[wrapper] +HB.mixin Record hom_isIMon T of Quiver T := + { hom_isIMon_private : forall A B, isOpIMonoid2 (@hom T A B) }. + +#[wrapper] +HB.mixin Record hom_isCMon T of Quiver T := + { hom_isCMon_private : forall A B, isOpCMonoid2 (@hom T A B) }. + +#[wrapper] +HB.mixin Record hom_isCIAlg T of Quiver T := + { hom_isCIAlg_private : forall A B, isOpCIAlgebra2 (@hom T A B) }. + +#[wrapper] +HB.mixin Record hom_isICAlg T of Quiver T := + { hom_isICAlg_private : forall A B, isOpICAlgebra2 (@hom T A B) }. + +#[wrapper] +HB.mixin Record hom_isACIAlg T of Quiver T := + { hom_isACIAlg_private : forall A B, isOpACIAlgebra2 (@hom T A B) }. + +#[wrapper] +HB.mixin Record hom_isCIMon T of Quiver T := + { hom_isCIMon_private : forall A B, isOpCIMonoid2 (@hom T A B) }. + +#[wrapper] +HB.mixin Record hom_isICMon T of Quiver T := + { hom_isICMon_private : forall A B, isOpICMonoid2 (@hom T A B) }. + + +(**************************************** ENRICHED STRUCTURES *******) + +(*** USED *) + +(** Base enriched structures *) + +HB.structure + Definition IAlgebra_enriched_quiver := + { Obj of isQuiver Obj & hom_isIAlg Obj }. + +HB.structure + Definition CAlgebra_enriched_quiver := + { Obj of isQuiver Obj & hom_isCAlg Obj }. + +HB.structure + Definition ZAlgebra_enriched_quiver := + { Obj of isQuiver Obj & hom_isZAlg Obj }. + +HB.structure + Definition AAlgebra_enriched_quiver := + { Obj of isQuiver Obj & hom_isAAlg Obj }. + + +(** Complex enriched structures *) + +HB.structure + Definition Monoid_enriched_quiver := + { Obj of isQuiver Obj & hom_isMon Obj }. + +HB.structure + Definition IMonoid_enriched_quiver := + { Obj of isQuiver Obj & hom_isMon Obj & hom_isIAlg Obj}. + +HB.structure + Definition CIAlgebra_enriched_quiver := + { Obj of isQuiver Obj & hom_isIAlg Obj & hom_isCAlg Obj}. + +HB.structure + Definition ACIAlgebra_enriched_quiver := + { Obj of isQuiver Obj & hom_isIAlg Obj & hom_isCAlg Obj & hom_isAAlg Obj}. + +HB.structure + Definition CIMonoid_enriched_quiver := + { Obj of isQuiver Obj & hom_isMon Obj & hom_isIAlg Obj & hom_isCAlg Obj}. + + +(*************************** LEMMA *****************************) + +Lemma zero_unique {B} (X: B -> B -> B) (zz0 zz1:B) : + left_id zz0 X -> right_id zz0 X -> left_id zz1 X -> right_id zz1 X -> + zz0 = zz1. + unfold left_id, right_id. + intros. + specialize (H0 zz1). + specialize (H1 zz0). + rewrite H1 in H0. + auto. +Qed. + +(*************************** INSTANCES *****************************) + +Require Import FunctionalExtensionality. + +(** INSTANCE 1 + +Object: Type, +Morphism: A -> option B +Structure: Monoid (from isOpMon2) +*) + +HB.instance Definition funQ := isQuiver.Build Type + (fun A B => A -> option B). + +Definition funQ_comp {A B: Type} (f g: hom A B) : hom A B := + fun x => + match f x with + | Some _ => f x + | _ => g x end. + +Program Definition funQ_isMon (A B: Type) : + isOpMon2 (hom A B) funQ_comp (fun (_:A) => None) := + isOpMon2.Build _ _ (fun (_:A) => None) _ _. +Obligation 1. +econstructor. +{- unfold left_id; intros. + unfold funQ_comp; auto. +} +{- unfold right_id; intros. + eapply functional_extensionality; intro a. + unfold funQ_comp. + destruct (x a); auto. +} +Qed. +Obligation 2. +econstructor. +{- unfold associative; intros. + eapply functional_extensionality; intro a. + unfold funQ_comp. + destruct (x a) eqn:K1. + simpl; auto. + destruct (y a); auto. +} +Qed. + +Program Definition funQ_isIAlg (A B: Type) : + isOpIAlg2 (hom A B) funQ_comp := + isOpIAlg2.Build _ _ _. +Obligation 1. +unfold idempotent; intros. +eapply functional_extensionality; intro a. +unfold funQ_comp. +destruct (x a); auto. +Qed. + +Program Definition funQ_isIMon (A B: Type) : + isOpIMon2 (hom A B) funQ_comp (fun (_:A) => None) := + isOpIMon2.Build (hom A B) _ _ _ _. +Obligation 1. +eapply funQ_isMon. +Qed. +Obligation 2. +eapply funQ_isIAlg. +Qed. + +HB.instance Definition funQ_isMonoid (A B: Type) : + isOpMonoid2 (hom A B) := + isOpMonoid2.Build (hom A B) funQ_comp (fun (_:A) => None) (funQ_isMon A B). + +HB.instance Definition funQ_isIAlgebra (A B: Type) : + isOpIAlgebra2 (hom A B) := + isOpIAlgebra2.Build (hom A B) funQ_comp (funQ_isIAlg A B). + +HB.instance Definition funQ_isIMonoid (A B: Type) : + isOpIMonoid2 (hom A B) := + isOpIMonoid2.Build (hom A B) funQ_comp (fun (_:A) => None) + (funQ_isIMon A B). + +Elpi Print HB.structure. + + +(** INSTANCE 2 + +Object: commutative monoid (by sigma type and isOpCMon2) +Morphism: (projT1 X) -> (projT1 Y) +Structure: commutative monoid (by isOpCMon2) +*) + +Open Scope type. + +#[verbose] +HB.instance Definition cmfunQ := + isQuiver.Build (sigT (fun A => (A -> A -> A) * A)) + (fun X Y => isOpCMon2 (projT1 X) (fst (projT2 X)) (snd (projT2 X)) -> + isOpCMon2 (projT1 Y) (fst (projT2 Y)) (snd (projT2 Y)) -> + (projT1 X) -> (projT1 Y)). + +Definition cmfunQ_comp {A B: sigT (fun A => (A -> A -> A) * A)} + (f g: @hom _ A B) : hom A B := + fun (ca: isOpCMon2 (projT1 A) (fst (projT2 A)) (snd (projT2 A))) + (cb: isOpCMon2 (projT1 B) (fst (projT2 B)) (snd (projT2 B))) a => + match (f ca cb a, g ca cb a) with + | (b1, b2) => (fst (projT2 B)) b1 b2 end. + +Program Definition cmfunQ_zero {A B: sigT (fun A => (A -> A -> A) * A)} : + hom A B. +Proof. + unfold hom; intros. + unfold isQuiver.hom. + unfold Quiver.cmonoid_enriched_cat_isQuiver_mixin. + unfold Quiver.class. + simpl; intros. + destruct B as [X [f x1]]; simpl. + exact x1. +Defined. + +Program Definition cmfunQ_isCMon (A B: sigT (fun A => (A -> A -> A) * A)) : + isOpCMon2 (hom A B) cmfunQ_comp cmfunQ_zero := + isOpCMon2.Build (hom A B) cmfunQ_comp _ _ _. +Obligation 1. +unfold cmfunQ_comp; simpl. +econstructor. +econstructor. +{- unfold left_id; intros. + eapply functional_extensionality; intro CMa. + eapply functional_extensionality; intro CMb. + eapply functional_extensionality; intro v. + remember CMb as CMb1. + destruct CMb. + destruct is_op_mon0. + destruct is_op_zalg0. + unfold left_id in add0r1. + simpl in add0r1. + unfold cmfunQ_zero. + eapply add0r1. +} +{- unfold right_id; intros. + eapply functional_extensionality; intro CMa. + eapply functional_extensionality; intro CMb. + eapply functional_extensionality; intro v. + remember CMb as CMb1. + destruct CMb. + destruct is_op_mon0. + destruct is_op_zalg0. + unfold right_id in addr1. + simpl in addr1. + unfold cmfunQ_zero. + eapply addr1. +} +econstructor. +{- unfold associative; intros. + eapply functional_extensionality; intro CMa. + eapply functional_extensionality; intro CMb. + eapply functional_extensionality; intro v. + remember CMb as CMb1. + destruct CMb. + destruct is_op_mon0. + destruct is_op_aalg0. + unfold associative in addA. + simpl in addA. + eapply addA. +} +Qed. +Obligation 2. + econstructor. + unfold cmfunQ_comp. + unfold commutative; simpl; intros. + eapply functional_extensionality; intro CMa. + eapply functional_extensionality; intro CMb. + eapply functional_extensionality; intro v. + remember CMb as CMb1. + destruct CMb. + destruct is_op_calg0. + simpl in addC. + eapply addC. +Qed. + +HB.instance Definition cmfunQ_isCMonoid + (A B: sigT (fun A => (A -> A -> A) * A)) : + isOpCMonoid2 (hom A B) := + isOpCMonoid2.Build (hom A B) cmfunQ_comp cmfunQ_zero (cmfunQ_isCMon A B). + +Elpi Print HB.structure. + + +(** INSTANCE 3 + +Object: associative commutative idempotent algebra + (by sigma type and isOpACIAlg2) +Morphism: (projT1 X) -> option (projT1 Y) +Structure: commutative idempotent monoid (by isOpCImon2) +*) + +(* hack *) +Definition sigTa1 := sigT (fun A => A -> A -> A). + +HB.instance Definition cimfunQ := + isQuiver.Build (sigTa1) + (fun X Y => isOpACIAlg2 (projT1 X) (projT2 X) -> + isOpACIAlg2 (projT1 Y) (projT2 Y) -> + (projT1 X) -> option (projT1 Y)). + +Definition cimfunQ_comp {A B: sigTa1} + (f g: hom A B) : hom A B := + fun (ca: isOpACIAlg2 (projT1 A) (projT2 A)) + (cb: isOpACIAlg2 (projT1 B) (projT2 B)) a => + match (f ca cb a, g ca cb a) with + | (Some b1, Some b2) => Some (projT2 B b1 b2) + | (Some b, None) => Some b + | (None, Some b) => Some b + | _ => None end. + +Definition cimfunQ_zero {A B: sigTa1} : hom A B := + fun _ _ _ => None. + +Program Definition cimfunQ_isCIMon (A B: sigTa1) : + isOpCIMon2 (hom A B) cimfunQ_comp cimfunQ_zero := + isOpCIMon2.Build _ _ cimfunQ_zero _ _. +Obligation 1. +econstructor. +econstructor. +econstructor. +{- unfold left_id; intros. + unfold cimfunQ_comp; simpl. + eapply functional_extensionality; intro ca. + eapply functional_extensionality; intro cb. + eapply functional_extensionality; intro v. + destruct (x ca cb v); auto. +} +{- unfold right_id; intros. + unfold cimfunQ_comp; simpl. + eapply functional_extensionality; intro ca. + eapply functional_extensionality; intro cb. + eapply functional_extensionality; intro v. + destruct (x ca cb v); auto. +} +econstructor. +{- unfold associative; intros. + unfold cimfunQ_comp; simpl. + eapply functional_extensionality; intro ca. + eapply functional_extensionality; intro cb. + eapply functional_extensionality; intro v. + remember cb as cb1. + destruct cb. + destruct is_op_aalg0. + simpl in addA. + unfold associative in addA. + destruct (x ca cb1 v); simpl; eauto. + {+ destruct (y ca cb1 v); simpl; eauto. + destruct (z ca cb1 v); simpl; eauto. + rewrite addA; auto. + destruct (z ca cb1 v); simpl; eauto. + } + {+ destruct (y ca cb1 v); simpl; eauto. + destruct (z ca cb1 v); simpl; eauto. + destruct (z ca cb1 v); simpl; eauto. + } +} +econstructor. +{- unfold idempotent; intros. + unfold cimfunQ_comp; simpl. + eapply functional_extensionality; intro ca. + eapply functional_extensionality; intro cb. + eapply functional_extensionality; intro v. + remember cb as cb1. + destruct cb. + destruct is_op_ialg0. + unfold idempotent in addI0. + simpl in addI0. + destruct (x ca cb1 v) eqn:K1. + rewrite addI0; auto. + auto. +} +Qed. +Obligation 2. +econstructor. +unfold commutative; intros. +unfold cimfunQ_comp; simpl. +eapply functional_extensionality; intro ca. +eapply functional_extensionality; intro cb. +eapply functional_extensionality; intro v. +remember cb as cb1. +destruct cb. +destruct is_op_calg0. +unfold commutative in addC. +simpl in addC. +destruct (x ca cb1 v); simpl; eauto. +destruct (y ca cb1 v); simpl; eauto. +rewrite addC; auto. +Qed. + +HB.instance Definition cimfunQ_isCIMonoid + (A B: sigTa1) : + isOpCIMonoid2 (hom A B) := + isOpCIMonoid2.Build (hom A B) cimfunQ_comp cimfunQ_zero + (cimfunQ_isCIMon A B). + +Elpi Print HB.structure. + diff --git a/tests/enriched_cat_case1.v b/tests/enriched_cat_case1.v new file mode 100644 index 000000000..845c62fc6 --- /dev/null +++ b/tests/enriched_cat_case1.v @@ -0,0 +1,292 @@ +From HB Require Import structures. +From Coq Require Import ssreflect ssrfun. + +(** Quiver *) + +HB.mixin Record isQuiver Obj := { hom : Obj -> Obj -> Type }. + +HB.structure Definition Quiver := { Obj of isQuiver Obj }. + + +(*************************************** OTHER MIXINS *************) +Require Import Coq.Program.Equality. +Require Import FunctionalExtensionality. + +HB.mixin Record isMagma T := { + mop : T -> T -> T; +}. +HB.structure Definition Magma := { T of isMagma T }. + +HB.mixin Record isMon T of isMagma T := { + munit : T; + massoc : associative (mop : T -> T -> T); + mlid : left_id munit mop; + mrid : right_id munit mop; + }. +#[verbose] +HB.structure Definition Mon := { T of isMon T }. + +HB.mixin Record isICAlg T of isMagma T := { + acomm : commutative (mop : T -> T -> T); + aidem : idempotent (mop : T -> T -> T); + }. +#[verbose] +HB.structure Definition ICAlg := { T of isICAlg T }. + +HB.mixin Record isICMon T of isMagma T := { + ica: isICAlg T ; + mon: isMon T; + }. +#[verbose] +HB.structure Definition ICMon := { T of isICMon T }. + + +(***** wrapping ****************************************************) + + +#[wrapper] +HB.mixin Record hom_isMagma T of Quiver T := + { hom_isMagma_private : forall A B, isMagma (@hom T A B) }. +HB.structure + Definition Magma_enriched_quiver := + { Obj of isQuiver Obj & hom_isMagma Obj }. + +(* +#[wrapper] +HB.mixin Record hom_isMon T of Quiver T := + { hom_isMon_private : forall A B, Mon (@hom T A B) }. +#[verbose] +HB.structure + Definition Mon_enriched_quiver := + { Obj of isQuiver Obj & hom_isMon Obj }. +*) +(* need to add explicitly Magma_enriched_quiver, otherwise switch + from mixin to structure *) +#[wrapper] +HB.mixin Record hom_isMon T of Magma_enriched_quiver T := + { hom_isMon_private : forall A B, isMon (@hom T A B) }. +HB.structure + Definition Mon_enriched_quiver := + { Obj of isQuiver Obj & hom_isMon Obj }. + +#[wrapper] +HB.mixin Record hom_isICAlg T of Magma_enriched_quiver T := + { hom_isICAlg_private : forall A B, isICAlg (@hom T A B) }. +HB.structure + Definition ICAlg_enriched_quiver := + { Obj of isQuiver Obj & hom_isICAlg Obj }. + +#[wrapper] +HB.mixin Record hom_isICMon T of Magma_enriched_quiver T := + { hom_isICMon_private : forall A B, isICMon (@hom T A B) }. +#[verbose] +HB.structure + Definition ICMon_enriched_quiver := + { Obj of isQuiver Obj & hom_isICMon Obj }. + +(*** factory ********************************************************) + +HB.factory Record isMICAlg T of Mon T := { + amop : T -> T -> T; + ameq : forall x y, amop x y = mop x y; + amcomm : commutative amop; + amidem : idempotent amop; + }. + +HB.builders Context T (f : isMICAlg T). + + Lemma amop_mop_eq : amop = mop. + destruct f; simpl. + eapply functional_extensionality; intro. + eapply functional_extensionality; intro. + auto. + Qed. + + Definition dum_comm := + @eq_rect (T -> T -> T) amop (@commutative T T) amcomm mop amop_mop_eq. + + Definition dum_idem := + @eq_rect (T -> T -> T) amop (@idempotent T) amidem mop amop_mop_eq. + + (* Expected failure: + HB.instance Definition b_IC : isICAlg T := + isICAlg.Build T amcomm amidem. + *) + + HB.instance Definition b_IC : isICAlg T := + isICAlg.Build T dum_comm dum_idem. + + Lemma M : isMon T. + destruct f; auto. + Qed. + + HB.instance Definition b_M : isICMon T := + isICMon.Build T b_IC M. + +HB.end. + +(*******************************************************************) + +(** INSTANCE 1 *********************************************** + +Object: Type, +Morphism: A -> option B +Structure: Monoid (from isMon) +*) +HB.instance Definition funQ := isQuiver.Build Type + (fun A B => A -> option B). + +Check Type : Quiver.type. + +Definition funQ_comp {A B: Type} (f g: hom A B) : hom A B := + fun x => + match f x with + | Some _ => f x + | _ => g x end. + +Definition funQ_zero {A B: Type} : hom A B := + fun (_:A) => None. + +(* does not work without declaring the Magma wrapper *) +HB.instance Definition funQ_isMagma (A B: Type) : + isMagma (hom A B) := isMagma.Build _ funQ_comp. + +Program Definition funQ_isMon (A B: Type) : isMon (hom A B) := + isMon.Build _ funQ_zero _ _ _. +Obligation 1. + unfold associative; intros. + eapply functional_extensionality; intro a. + unfold mop; simpl. + unfold funQ_comp. + destruct (x a) eqn:K1. + simpl; auto. + destruct (y a); auto. +Qed. +Obligation 2. + unfold left_id; intros. + unfold funQ_comp; auto. +Qed. +Obligation 3. + unfold right_id, mop; simpl; intros. + unfold funQ_zero, funQ_comp; simpl. + eapply functional_extensionality; intro a. + destruct (x a); auto. +Qed. + +Fail Check Type : Mon_enriched_quiver.type. +Fail Check hom (nat:Type) nat: Mon.type. + +HB.instance Definition funQ_Monoid (A B: Type) : + isMon (hom A B) := funQ_isMon A B. + +Check Type : Mon_enriched_quiver.type. +Check hom (nat:Type) nat: Mon.type. + + +(** INSTANCE 2 ********************************************** + +Object: ICMon.type +Morphism: ICMon.sort A -> ICMon.sort B +Structure: idempotent commutative monoid (by ICMon) +*) + +#[verbose] +HB.instance Definition icmfunQ := + isQuiver.Build ICMon.type + (fun A B => (ICMon.sort A) -> (ICMon.sort B)). + +Definition icmfunQ_comp {A B: ICMon.type} (f g: hom A B) : hom A B := + fun x => @mop B (f x) (g x). + +Definition icmfunQ_zero {A B: ICMon.type} : hom A B. + destruct B. + unfold hom; simpl; intro. + destruct class. + destruct enriched_cat_case1_isICMon_mixin. + destruct mon0. + exact munit0. +Defined. + +(* does not work without declaring the Magma wrapper *) +HB.instance Definition icmfunQ_isMagma (A B: ICMon.type) : + isMagma (hom A B) := isMagma.Build _ icmfunQ_comp. + +(* does not type-check without the Magma instance *) +Program Definition icmfunQ_isMon (A B: ICMon.type) : + isMon (hom A B) := isMon.Build (hom A B) icmfunQ_zero _ _ _. +Obligation 1. +unfold associative, mop; simpl; intros. +unfold icmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isICMon_mixin. +simpl in *. +destruct mon0. +eapply massoc0; auto. +Qed. +Obligation 2. +unfold left_id, mop; simpl; intros. +unfold icmfunQ_comp, icmfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isICMon_mixin. +destruct mon0. +auto. +Qed. +Obligation 3. +unfold right_id, mop; simpl; intros. +unfold icmfunQ_comp, icmfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isICMon_mixin. +destruct mon0. +auto. +Qed. + +Program Definition icmfunQ_isICAlg (A B: ICMon.type) : + isICAlg (hom A B) := isICAlg.Build (hom A B) _ _. +Obligation 1. +unfold commutative, mop; simpl; intros. +unfold icmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isICMon_mixin. +simpl in *. +destruct ica0. +eapply acomm0; auto. +Qed. +Obligation 2. +unfold idempotent, mop; simpl; intros. +unfold icmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isICMon_mixin. +simpl in *. +destruct ica0. +eapply aidem0; auto. +Qed. + +Program Definition icmfunQ_isICMon (A B: ICMon.type) : + isICMon (hom A B) := isICMon.Build (hom A B) _ _. +Obligation 1. +eapply icmfunQ_isICAlg. +Qed. +Obligation 2. +eapply icmfunQ_isMon. +Qed. + +HB.instance Definition icmfunQ_isMonoid (A B: ICMon.type) : + isMon (hom A B) := icmfunQ_isMon A B. + +HB.instance Definition icmfunQ_isICAlgebra (A B: ICMon.type) : + isICAlg (hom A B) := icmfunQ_isICAlg A B. + +HB.instance Definition icmfunQ_isICMonoid (A B: ICMon.type) : + isICMon (hom A B) := icmfunQ_isICMon A B. + +Check ICMon.type : ICAlg_enriched_quiver.type. diff --git a/tests/enriched_cat_case2.v b/tests/enriched_cat_case2.v new file mode 100644 index 000000000..8f9fb062a --- /dev/null +++ b/tests/enriched_cat_case2.v @@ -0,0 +1,115 @@ +From HB Require Import structures. +From Coq Require Import ssreflect ssrfun. + +(** Quiver *) + +HB.mixin Record isQuiver Obj := { hom : Obj -> Obj -> Type }. + +HB.structure Definition Quiver := { Obj of isQuiver Obj }. + + +(*************************************** OTHER MIXINS *************) +Require Import Coq.Program.Equality. +Require Import FunctionalExtensionality. + +HB.mixin Record isMon T := { + munit : T; + mop : T -> T -> T; + massoc : associative mop; + mlid : left_id munit mop; + mrid : right_id munit mop; + }. +#[verbose] +HB.structure Definition Mon := { T of isMon T }. + +HB.mixin Record isICAlg T := { + aop : T -> T -> T; + acomm : commutative aop; + aidem : idempotent aop; + }. +#[verbose] +HB.structure Definition ICAlg := { T of isICAlg T }. + +HB.mixin Record isICMon T := { + maunit : T; + aop : T -> T -> T; + maassoc : associative aop; + malid : left_id maunit aop; + marid : right_id maunit aop; + macomm : commutative aop; + maidem : idempotent aop; + }. +#[verbose] +HB.structure Definition ICMon := { T of isICMon T & Mon T & ICAlg T }. + +(* +Lemma isICMon2isMon T : isICMon T -> isMon T. + intro X. + destruct X. + econstructor; eauto. +Qed. + +Lemma isICMon2isICAlg T : isICMon T -> isICAlg T. + intro X. + destruct X. + econstructor; eauto. +Qed. + *) + +(* +#[wrapper] +HB.mixin Record hom_isICAlg T of Quiver T := + { hom_isICAlg_private : forall A B, isICAlg (@hom T A B) }. + +#[wrapper] +HB.mixin Record hom_isMon T of Quiver T := + { hom_isMon_private : forall A B, isMon (@hom T A B) }. + +HB.structure + Definition Mon_enriched_quiver := + { Obj of isQuiver Obj & hom_isMon Obj }. + +HB.structure + Definition ICAlg_enriched_quiver := + { Obj of isQuiver Obj & hom_isICAlg Obj }. +*) + +#[wrapper] +HB.mixin Record hom_isICMon T of Quiver T := + { hom_isICMon_private : forall A B, isICMon (@hom T A B) }. +#[verbose] +HB.structure + Definition ICMon_enriched_quiver := + { Obj of isQuiver Obj & hom_isICMon Obj }. + + +HB.factory Record isMICAlg T of Mon T := { + amop : T -> T -> T; + ameq : forall x y, amop x y = mop x y; + amcomm : commutative amop; + amidem : idempotent amop; + }. + +HB.builders Context T (f : isMICAlg T). + + Lemma amop_mop_eq : amop = mop. + destruct f; simpl. + eapply functional_extensionality; intro. + eapply functional_extensionality; intro. + auto. + Qed. + + Definition dum_comm := + @eq_rect (T -> T -> T) amop (@commutative T T) amcomm mop amop_mop_eq. + + Definition dum_idem := + @eq_rect (T -> T -> T) amop (@idempotent T) amidem mop amop_mop_eq. + + HB.instance Definition b_A : isICAlg T := + isICAlg.Build T mop dum_comm dum_idem. + + HB.instance Definition b_M : isICMon T := + isICMon.Build T munit mop massoc mlid mrid dum_comm dum_idem. + +HB.end. + diff --git a/tests/enriched_cat_case3.v b/tests/enriched_cat_case3.v new file mode 100644 index 000000000..6185fc7f1 --- /dev/null +++ b/tests/enriched_cat_case3.v @@ -0,0 +1,94 @@ +From HB Require Import structures. +From Coq Require Import ssreflect ssrfun. + +(** Quiver *) + +HB.mixin Record isQuiver Obj := { hom : Obj -> Obj -> Type }. + +HB.structure Definition Quiver := { Obj of isQuiver Obj }. + + +(*************************************** OTHER MIXINS *************) +Require Import Coq.Program.Equality. +Require Import FunctionalExtensionality. + +HB.mixin Record isMon T := { + munit : T; + mop : T -> T -> T; + massoc : associative mop; + mlid : left_id munit mop; + mrid : right_id munit mop; + }. +HB.structure Definition Mon := { T of isMon T }. + +HB.mixin Record isICAlg T := { + aop : T -> T -> T; + acomm : commutative aop; + aidem : idempotent aop; + }. +HB.structure Definition ICAlg := { T of isICAlg T }. + +HB.mixin Record isICMon T of ICAlg T := { + maunit : T; + maop : T -> T -> T; + maeq : forall x y, maop x y = aop x y; + maassoc : associative maop; + malid : left_id maunit maop; + marid : right_id maunit maop; + }. +HB.structure Definition ICMon := { T of isICMon T & isICAlg T }. + +#[wrapper] +HB.mixin Record hom_isMon T of Quiver T := + { hom_isMon_private : forall A B, isMon (@hom T A B) }. + +#[wrapper] +HB.mixin Record hom_isICAlg T of Quiver T := + { hom_isICAlg_private : forall A B, isICAlg (@hom T A B) }. + +HB.structure + Definition Mon_enriched_quiver := + { Obj of isQuiver Obj & hom_isMon Obj }. + +HB.structure + Definition ICAlg_enriched_quiver := + { Obj of isQuiver Obj & hom_isICAlg Obj }. + +Fail #[wrapper] +HB.mixin Record hom_isICMon T of Quiver T := + { hom_isICMon_private : forall A B, isICMon (@hom T A B) }. + +HB.factory Record isMICAlg T of Mon T := { + amop : T -> T -> T; + ameq : forall x y, amop x y = mop x y; + amcomm : commutative amop; + amidem : idempotent amop; + }. + +HB.builders Context T (f : isMICAlg T). + + Lemma amop_mop_eq : amop = mop. + destruct f; simpl. + eapply functional_extensionality; intro. + eapply functional_extensionality; intro. + auto. + Qed. + + Definition dum_comm := + @eq_rect (T -> T -> T) amop (@commutative T T) amcomm mop amop_mop_eq. + + Definition dum_idem := + @eq_rect (T -> T -> T) amop (@idempotent T) amidem mop amop_mop_eq. + + HB.instance Definition b_A : isICAlg T := + isICAlg.Build T mop dum_comm dum_idem. + + Lemma mop_aop_eq (x y: T) : mop x y = aop x y. + destruct f; auto. + Qed. + + HB.instance Definition b_M : isICMon T := + isICMon.Build T munit mop mop_aop_eq massoc mlid mrid. + +HB.end. + diff --git a/tests/enriched_cat_case4.v b/tests/enriched_cat_case4.v new file mode 100644 index 000000000..92479861f --- /dev/null +++ b/tests/enriched_cat_case4.v @@ -0,0 +1,278 @@ +From HB Require Import structures. +From Coq Require Import ssreflect ssrfun. + +(** Quiver *) + +HB.mixin Record isQuiver Obj := { hom : Obj -> Obj -> Type }. + +HB.structure Definition Quiver := { Obj of isQuiver Obj }. + + +(*************************************** OTHER MIXINS *************) +Require Import Coq.Program.Equality. +Require Import FunctionalExtensionality. + +HB.mixin Record isM T (munit: T) (mop: T -> T -> T) := { + massoc : associative mop; + mlid : left_id munit mop; + mrid : right_id munit mop; + }. + +HB.mixin Record isMon T := { + munit : T; + mop : T -> T -> T; + mism : isM T munit mop; + }. +#[verbose] +HB.structure Definition Mon := { T of isMon T }. + +HB.mixin Record isIC T (aop: T -> T -> T) := { + comm : commutative aop; + idem : idempotent aop; + }. + +HB.mixin Record isICAlg T := { + aop : T -> T -> T; + ica : isIC T aop ; + }. +#[verbose] +HB.structure Definition ICAlg := { T of isICAlg T }. + +HB.mixin Record isICMon T := { + maunit : T; + maop : T -> T -> T; + mica : isIC T maop; + mon : isM T maunit maop; + }. +HB.structure Definition ICMon := { T of isICMon T & Mon T & ICAlg T }. + + +(*** wrapping ******************************************************) + +#[wrapper] +HB.mixin Record hom_isMon T of Quiver T := + { hom_isMon_private : forall A B, isMon (@hom T A B) }. +#[verbose] +HB.structure Definition Mon_enriched_quiver := + { Obj of isQuiver Obj & hom_isMon Obj }. + +#[wrapper] +HB.mixin Record hom_isICAlg T of Quiver T := + { hom_isICAlg_private : forall A B, isICAlg (@hom T A B) }. +#[verbose] +HB.structure Definition ICAlg_enriched_quiver := + { Obj of isQuiver Obj & hom_isICAlg Obj }. + +#[wrapper] +HB.mixin Record hom_isICMon T of Quiver T := + { hom_isICMon_private : forall A B, isICMon (@hom T A B) }. +#[verbose] +HB.structure Definition ICMon_enriched_quiver := + { Obj of isQuiver Obj & hom_isICMon Obj }. + +(*** factory ********************************************************) + +HB.factory Record isMICAlg T of Mon T := { + amop : T -> T -> T; + ameq : forall x y, amop x y = mop x y; + amcomm : commutative amop; + amidem : idempotent amop; + }. + +HB.builders Context T (f : isMICAlg T). + + Lemma amop_mop_eq : amop = mop. + destruct f; simpl. + eapply functional_extensionality; intro. + eapply functional_extensionality; intro. + auto. + Qed. + + Definition dum_comm := + @eq_rect (T -> T -> T) amop (@commutative T T) amcomm mop amop_mop_eq. + + Definition dum_idem := + @eq_rect (T -> T -> T) amop (@idempotent T) amidem mop amop_mop_eq. + + Definition b_A : isIC T mop := + isIC.Build T mop dum_comm dum_idem. + + HB.instance Definition bb_A : isICAlg T := + isICAlg.Build T mop b_A. + + Lemma mop_aop_eq (x y: T) : mop x y = aop x y. + destruct f; auto. + Qed. + + Lemma b_M : isM T munit mop. + destruct f. + exact mism. + Qed. + + HB.instance Definition bb_M : isICMon T := + isICMon.Build T munit mop b_A b_M. + +HB.end. + +(**********************************************************************) + +(** INSTANCE 1 ********************************************************* + +Object: Type, +Morphism: A -> option B +Structure: Monoid (from isMon) +*) + +HB.instance Definition funQ := isQuiver.Build Type + (fun A B => A -> option B). + +Definition funQ_comp {A B: Type} (f g: hom A B) : hom A B := + fun x => + match f x with + | Some _ => f x + | _ => g x end. + +Definition funQ_zero {A B: Type} : hom A B := + fun (_:A) => None. + +Program Definition funQ_isM (A B: Type) : + isM (hom A B) funQ_zero funQ_comp := + isM.Build _ funQ_zero funQ_comp _ _ _. +Obligation 1. + unfold associative; intros. + unfold funQ_comp. + eapply functional_extensionality; intro a; simpl. + destruct (x a) eqn:K1. + simpl; auto. + destruct (y a); auto. +Qed. +Obligation 2. + unfold left_id; intros. + unfold funQ_comp; auto. +Qed. +Obligation 3. + unfold right_id; simpl; intros. + unfold funQ_zero, funQ_comp; simpl. + eapply functional_extensionality; intro a. + destruct (x a); auto. +Qed. + +HB.instance Definition funQ_isMonoid (A B: Type) : + isMon (hom A B) := + isMon.Build (hom A B) funQ_zero funQ_comp (funQ_isM A B). + + +(** INSTANCE 2 ********************************************** + +Object: ICMon.type +Morphism: ICMon.sort A -> ICMon.sort B +Structure: idempotent commutative monoid (by ICMon) +*) + +#[verbose] +HB.instance Definition icmfunQ := + isQuiver.Build ICMon.type + (fun A B => (ICMon.sort A) -> (ICMon.sort B)). + +Definition icmfunQ_comp {A B: ICMon.type} (f g: hom A B) : hom A B := + fun x => @maop B (f x) (g x). + +Definition icmfunQ_zero {A B: ICMon.type} : hom A B := fun _ => @maunit B. + +(* does not type-check without the Magma instance *) +Program Definition icmfunQ_isM (A B: ICMon.type) : + isM (hom A B) (@icmfunQ_zero A B) (@icmfunQ_comp A B) := + isM.Build (hom A B) icmfunQ_zero icmfunQ_comp _ _ _. +Obligation 1. +unfold associative; simpl; intros. +unfold icmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B eqn:B1. +destruct class eqn:class1. +destruct enriched_cat_case4_isMon_mixin eqn:C1. +simpl in *. +unfold maop; simpl. +unfold isICMon.maop; simpl. +destruct enriched_cat_case4_isICMon_mixin eqn:D1. +destruct mon0. +eapply massoc. +Qed. +Obligation 2. +unfold left_id; simpl; intros. +unfold icmfunQ_comp, icmfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B eqn: B1. +destruct class eqn: class1. +destruct enriched_cat_case4_isMon_mixin eqn:C1; simpl in *. +destruct mism0 eqn:mism1. +destruct enriched_cat_case4_isICMon_mixin eqn:D1; simpl in *. +destruct mon0 eqn:mon1; simpl in *. +unfold maop; simpl. +eapply mlid0. +Qed. +Obligation 3. +unfold right_id; simpl; intros. +unfold icmfunQ_comp, icmfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B eqn: B1. +destruct class eqn: class1. +destruct enriched_cat_case4_isMon_mixin eqn:C1; simpl in *. +destruct mism0 eqn:mism1. +destruct enriched_cat_case4_isICMon_mixin eqn:D1; simpl in *. +destruct mon0 eqn:mon1; simpl in *. +unfold maop; simpl. +eapply mrid0. +Qed. + +Program Definition icmfunQ_isIC (A B: ICMon.type) : + isIC (hom A B) icmfunQ_comp := isIC.Build (hom A B) icmfunQ_comp _ _. +Obligation 1. +unfold commutative; simpl; intros. +unfold icmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +unfold maop. +unfold isICMon.maop; simpl. +destruct B eqn:B1. +destruct class eqn:class1. +destruct enriched_cat_case4_isICMon_mixin eqn:D1. +simpl. +destruct mica0. +eapply comm. +Qed. +Obligation 2. +unfold idempotent, mop; simpl; intros. +unfold icmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +unfold maop. +unfold isICMon.maop; simpl. +destruct B eqn:B1. +destruct class eqn:class1. +destruct enriched_cat_case4_isICMon_mixin eqn:D1. +simpl. +destruct mica0. +eapply idem. +Qed. + +Program Definition icmfunQ_isICMon (A B: ICMon.type) : + isICMon (hom A B) := isICMon.Build (hom A B) icmfunQ_zero icmfunQ_comp _ _. +Obligation 1. +eapply icmfunQ_isIC. +Qed. +Obligation 2. +eapply icmfunQ_isM. +Qed. + +HB.instance Definition icmfunQ_isMonoid (A B: ICMon.type) : + isMon (hom A B) := + isMon.Build (hom A B) icmfunQ_zero icmfunQ_comp (icmfunQ_isM A B). + +HB.instance Definition icmfunQ_isICAlgebra (A B: ICMon.type) : + isICAlg (hom A B) := + isICAlg.Build (hom A B) icmfunQ_comp (icmfunQ_isIC A B). + +HB.instance Definition icmfunQ_isICMonoid (A B: ICMon.type) : + isICMon (hom A B) := icmfunQ_isICMon A B. + + + + diff --git a/tests/enriched_cat_case5.v b/tests/enriched_cat_case5.v new file mode 100644 index 000000000..f27137dd5 --- /dev/null +++ b/tests/enriched_cat_case5.v @@ -0,0 +1,562 @@ +From HB Require Import structures. +From Coq Require Import ssreflect ssrfun. + +(** Quiver *) + +HB.mixin Record isQuiver Obj := { hom : Obj -> Obj -> Type }. + +HB.structure Definition Quiver := { Obj of isQuiver Obj }. + + +(*************************************** OTHER MIXINS *************) +Require Import Coq.Program.Equality. +Require Import FunctionalExtensionality. + +HB.mixin Record isMagma T := { + mop : T -> T -> T; +}. +HB.structure Definition Magma := { T of isMagma T }. + +HB.mixin Record isMon T of isMagma T := { + munit : T; + massoc : associative (mop : T -> T -> T); + mlid : left_id munit mop; + mrid : right_id munit mop; + }. +#[verbose] +HB.structure Definition Mon := { T of isMon T }. + +HB.mixin Record isCAlg T of isMagma T := { + acomm : commutative (mop : T -> T -> T); + }. +#[verbose] +HB.structure Definition CAlg := { T of isCAlg T }. + +HB.mixin Record isIAlg T of isMagma T := { + aidem : idempotent (mop : T -> T -> T); + }. +#[verbose] +HB.structure Definition IAlg := { T of isIAlg T }. + +HB.mixin Record isICAlg T of isMagma T := { + isca : isCAlg T; + isia : isIAlg T; + }. +#[verbose] +HB.structure Definition ICAlg := { T of isICAlg T }. + +HB.mixin Record isCMon T of isMagma T := { + cca: isCAlg T ; + cmon: isMon T; + }. +#[verbose] +HB.structure Definition CMon := { T of isCMon T }. + +HB.mixin Record isIMon T of isMagma T := { + iia: isIAlg T ; + imon: isMon T; + }. +#[verbose] +HB.structure Definition IMon := { T of isIMon T }. + +HB.mixin Record isICMon T of isMagma T := { + ica: isICAlg T ; + mon: isMon T; + }. +#[verbose] +HB.structure Definition ICMon := { T of isICMon T }. + + +(***** wrapping ****************************************************) + +#[wrapper] +HB.mixin Record hom_isMagma T of Quiver T := + { hom_isMagma_private : forall A B, isMagma (@hom T A B) }. +HB.structure + Definition Magma_enriched_quiver := + { Obj of isQuiver Obj & hom_isMagma Obj }. + +(* +#[wrapper] +HB.mixin Record hom_isMon T of Quiver T := + { hom_isMon_private : forall A B, Mon (@hom T A B) }. +*) +(* need to add explicitly Magma_enriched_quiver, otherwise switch + from mixin to structure *) +#[wrapper] +HB.mixin Record hom_isMon T of Magma_enriched_quiver T := + { hom_isMon_private : forall A B, isMon (@hom T A B) }. +HB.structure + Definition Mon_enriched_quiver := + { Obj of isQuiver Obj & hom_isMon Obj }. + +#[wrapper] +HB.mixin Record hom_isCAlg T of Magma_enriched_quiver T := + { hom_isCAlg_private : forall A B, isCAlg (@hom T A B) }. +HB.structure + Definition CAlg_enriched_quiver := + { Obj of isQuiver Obj & hom_isCAlg Obj }. + +#[wrapper] +HB.mixin Record hom_isIAlg T of Magma_enriched_quiver T := + { hom_isIAlg_private : forall A B, isIAlg (@hom T A B) }. +HB.structure + Definition IAlg_enriched_quiver := + { Obj of isQuiver Obj & hom_isIAlg Obj }. + +#[wrapper] +HB.mixin Record hom_isICAlg T of Magma_enriched_quiver T := + { hom_isICAlg_private : forall A B, isICAlg (@hom T A B) }. +HB.structure + Definition ICAlg_enriched_quiver := + { Obj of isQuiver Obj & hom_isICAlg Obj }. + +#[wrapper] +HB.mixin Record hom_isCMon T of Magma_enriched_quiver T := + { hom_isCMon_private : forall A B, isCMon (@hom T A B) }. +#[verbose] +HB.structure + Definition CMon_enriched_quiver := + { Obj of isQuiver Obj & hom_isCMon Obj }. + +#[wrapper] +HB.mixin Record hom_isIMon T of Magma_enriched_quiver T := + { hom_isIMon_private : forall A B, isIMon (@hom T A B) }. +#[verbose] +HB.structure + Definition IMon_enriched_quiver := + { Obj of isQuiver Obj & hom_isIMon Obj }. + +#[wrapper] +HB.mixin Record hom_isICMon T of Magma_enriched_quiver T := + { hom_isICMon_private : forall A B, isICMon (@hom T A B) }. +#[verbose] +HB.structure + Definition ICMon_enriched_quiver := + { Obj of isQuiver Obj & hom_isICMon Obj }. + +(*** factory ********************************************************) + +HB.factory Record isMICAlg T of Mon T := { + amop : T -> T -> T; + ameq : forall x y, amop x y = mop x y; + amcomm : commutative amop; + amidem : idempotent amop; + }. + +HB.builders Context T (_ : isMICAlg T). + + Lemma amop_mop_eq : amop = mop. + (* destruct f; simpl. *) + eapply functional_extensionality; intro. + eapply functional_extensionality; intro. + apply ameq. + Qed. + + Definition dum_comm := + @eq_rect (T -> T -> T) amop (@commutative T T) amcomm mop amop_mop_eq. + + Definition dum_idem := + @eq_rect (T -> T -> T) amop (@idempotent T) amidem mop amop_mop_eq. + + HB.instance Definition b_C : isCAlg T := + isCAlg.Build T dum_comm. + + HB.instance Definition b_I : isIAlg T := + isIAlg.Build T dum_idem. + + HB.instance Definition b_IC : isICAlg T := + isICAlg.Build T b_C b_I. + + Lemma M : isMon T. + destruct f; auto. + Qed. + + HB.instance Definition b_M : isICMon T := + isICMon.Build T b_IC M. + +HB.end. + +(*******************************************************************) + +(** INSTANCE 1 *********************************************** + +Object: Type, +Morphism: A -> option B +Structure: Monoid (from isMon) +*) + +HB.instance Definition funQ := isQuiver.Build Type + (fun A B => A -> option B). + +Check Type : Quiver.type. + +Definition funQ_comp {A B: Type} (f g: hom A B) : hom A B := + fun x => + match f x with + | Some _ => f x + | _ => g x end. + +Definition funQ_zero {A B: Type} : hom A B := + fun (_:A) => None. + +(* does not work without declaring the Magma wrapper *) +HB.instance Definition funQ_isMagma (A B: Type) : + isMagma (hom A B) := isMagma.Build _ funQ_comp. + +Program Definition funQ_isMon (A B: Type) : isMon (hom A B) := + isMon.Build _ funQ_zero _ _ _. +Obligation 1. + unfold associative; intros. + eapply functional_extensionality; intro a. + unfold mop; simpl. + unfold funQ_comp. + destruct (x a) eqn:K1. + simpl; auto. + destruct (y a); auto. +Qed. +Obligation 2. + unfold left_id; intros. + unfold funQ_comp; auto. +Qed. +Obligation 3. + unfold right_id, mop; simpl; intros. + unfold funQ_zero, funQ_comp; simpl. + eapply functional_extensionality; intro a. + destruct (x a); auto. +Qed. + +Program Definition funQ_isIAlg (A B: Type) : + isIAlg (hom A B) := isIAlg.Build _ _. +Obligation 1. +unfold idempotent; intros. +eapply functional_extensionality; intro a. +unfold mop; simpl. +unfold funQ_comp; simpl. +destruct (x a); auto. +Qed. + +Program Definition funQ_isIMon (A B: Type) : + isIMon (hom A B) := isIMon.Build (hom A B) _ _. +Obligation 1. +eapply funQ_isIAlg. +Qed. +Obligation 2. +eapply funQ_isMon. +Qed. + +HB.instance Definition funQ_IAlgebra (A B: Type) : + isIAlg (hom A B) := funQ_isIAlg A B. + +HB.instance Definition funQ_IMonoid (A B: Type) : + isIMon (hom A B) := funQ_isIMon A B. + +Check Type : IMon_enriched_quiver.type. + + +(** INSTANCE 2 ********************************************** + +Object: CMon.type +Morphism: CMon.sort A -> CMon.sort B +Structure: commutative monoid (by CMon) +*) + +#[verbose] +HB.instance Definition cmfunQ := + isQuiver.Build CMon.type + (fun A B => (CMon.sort A) -> (CMon.sort B)). + +Definition cmfunQ_comp {A B: CMon.type} (f g: hom A B) : hom A B := + fun x => @mop B (f x) (g x). + +Definition cmfunQ_zero {A B: CMon.type} : hom A B. + destruct B. + unfold hom; simpl; intro. + destruct class. + destruct enriched_cat_case1_isCMon_mixin. + destruct cmon0. + exact munit0. +Defined. + +(* does not work without declaring the Magma wrapper *) +HB.instance Definition cmfunQ_isMagma (A B: CMon.type) : + isMagma (hom A B) := isMagma.Build _ cmfunQ_comp. + +(* does not type-check without the Magma instance *) +Program Definition cmfunQ_isMon (A B: CMon.type) : + isMon (hom A B) := isMon.Build (hom A B) cmfunQ_zero _ _ _. +Obligation 1. +unfold associative, mop; simpl; intros. +unfold cmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isCMon_mixin. +simpl in *. +destruct cmon0. +eapply massoc0; auto. +Qed. +Obligation 2. +unfold left_id, mop; simpl; intros. +unfold cmfunQ_comp, cmfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isCMon_mixin. +destruct cmon0. +auto. +Qed. +Obligation 3. +unfold right_id, mop; simpl; intros. +unfold cmfunQ_comp, cmfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isCMon_mixin. +destruct cmon0. +auto. +Qed. + +Program Definition cmfunQ_isCAlg (A B: CMon.type) : + isCAlg (hom A B) := isCAlg.Build (hom A B) _. +Obligation 1. +unfold commutative, mop; simpl; intros. +unfold cmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isCMon_mixin. +simpl in *. +destruct cca0. +eapply acomm0; auto. +Qed. + +Program Definition cmfunQ_isCMon (A B: CMon.type) : + isCMon (hom A B) := isCMon.Build (hom A B) _ _. +Obligation 1. +eapply cmfunQ_isCAlg. +Qed. +Obligation 2. +eapply cmfunQ_isMon. +Qed. + +HB.instance Definition cmfunQ_isMonoid (A B: CMon.type) : + isMon (hom A B) := cmfunQ_isMon A B. + +HB.instance Definition cmfunQ_isICAlgebra (A B: CMon.type) : + isCAlg (hom A B) := cmfunQ_isCAlg A B. + +HB.instance Definition icmfunQ_isCMonoid (A B: CMon.type) : + isCMon (hom A B) := cmfunQ_isCMon A B. + +Check CMon.type : CAlg_enriched_quiver.type. + +(*********************************************************) + +(* +Object: IMon.type +Morphism: IMon.sort A -> IMon.sort B +Structure: idempotent monoid (by IMon) +*) + +#[verbose] +HB.instance Definition imfunQ := + isQuiver.Build IMon.type + (fun A B => (IMon.sort A) -> (IMon.sort B)). + +Definition imfunQ_comp {A B: IMon.type} (f g: hom A B) : hom A B := + fun x => @mop B (f x) (g x). + +Definition imfunQ_zero {A B: IMon.type} : hom A B. + destruct B. + unfold hom; simpl; intro. + destruct class. + destruct enriched_cat_case1_isIMon_mixin. + destruct imon0. + exact munit0. +Defined. + +(* does not work without declaring the Magma wrapper *) +HB.instance Definition imfunQ_isMagma (A B: IMon.type) : + isMagma (hom A B) := isMagma.Build _ imfunQ_comp. + +(* does not type-check without the Magma instance *) +Program Definition imfunQ_isMon (A B: IMon.type) : + isMon (hom A B) := isMon.Build (hom A B) imfunQ_zero _ _ _. +Obligation 1. +unfold associative, mop; simpl; intros. +unfold imfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isIMon_mixin. +simpl in *. +destruct imon0. +eapply massoc0; auto. +Qed. +Obligation 2. +unfold left_id, mop; simpl; intros. +unfold imfunQ_comp, imfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isIMon_mixin. +destruct imon0. +auto. +Qed. +Obligation 3. +unfold right_id, mop; simpl; intros. +unfold imfunQ_comp, imfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isIMon_mixin. +destruct imon0. +auto. +Qed. + +Program Definition imfunQ_isIAlg (A B: IMon.type) : + isIAlg (hom A B) := isIAlg.Build (hom A B) _. +Obligation 1. +unfold idempotent, mop; simpl; intros. +unfold imfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isIMon_mixin. +simpl in *. +destruct iia0; auto. +Qed. + +Program Definition imfunQ_isIMon (A B: IMon.type) : + isIMon (hom A B) := isIMon.Build (hom A B) _ _. +Obligation 1. +eapply imfunQ_isIAlg. +Qed. +Obligation 2. +eapply imfunQ_isMon. +Qed. + +HB.instance Definition imfunQ_isMonoid (A B: IMon.type) : + isMon (hom A B) := imfunQ_isMon A B. + +HB.instance Definition imfunQ_isIAlgebra (A B: IMon.type) : + isIAlg (hom A B) := imfunQ_isIAlg A B. + +HB.instance Definition imfunQ_isIMonoid (A B: IMon.type) : + isIMon (hom A B) := imfunQ_isIMon A B. + +Check IMon.type : IAlg_enriched_quiver.type. + +(*********************************************************) +(* +Object: ICMon.type +Morphism: ICMon.sort A -> ICMon.sort B +Structure: idempotent commutative monoid (by ICMon) +*) + +#[verbose] +HB.instance Definition icmfunQ := + isQuiver.Build ICMon.type + (fun A B => (ICMon.sort A) -> (ICMon.sort B)). + +Definition icmfunQ_comp {A B: ICMon.type} (f g: hom A B) : hom A B := + fun x => @mop B (f x) (g x). + +Definition icmfunQ_zero {A B: ICMon.type} : hom A B. + destruct B. + unfold hom; simpl; intro. + destruct class. + destruct enriched_cat_case1_isICMon_mixin. + destruct mon0. + exact munit0. +Defined. + +(* does not work without declaring the Magma wrapper *) +HB.instance Definition icmfunQ_isMagma (A B: ICMon.type) : + isMagma (hom A B) := isMagma.Build _ icmfunQ_comp. + +(* does not type-check without the Magma instance *) +Program Definition icmfunQ_isMon (A B: ICMon.type) : + isMon (hom A B) := isMon.Build (hom A B) icmfunQ_zero _ _ _. +Obligation 1. +unfold associative, mop; simpl; intros. +unfold icmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isICMon_mixin. +simpl in *. +destruct mon0. +eapply massoc0; auto. +Qed. +Obligation 2. +unfold left_id, mop; simpl; intros. +unfold icmfunQ_comp, icmfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isICMon_mixin. +destruct mon0. +auto. +Qed. +Obligation 3. +unfold right_id, mop; simpl; intros. +unfold icmfunQ_comp, icmfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isICMon_mixin. +destruct mon0. +auto. +Qed. + + +Program Definition icmfunQ_isICAlg (A B: ICMon.type) : + isICAlg (hom A B) := isICAlg.Build (hom A B) _ _. +Obligation 1. +econstructor. +unfold commutative, mop; simpl; intros. +unfold icmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isICMon_mixin. +simpl in *. +destruct ica0. +destruct isca0. +eapply acomm0; auto. +Qed. +Obligation 2. +econstructor. +unfold idempotent, mop; simpl; intros. +unfold icmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isICMon_mixin. +simpl in *. +destruct ica0. +destruct isia0. +eapply aidem0; auto. +Qed. + +Program Definition icmfunQ_isICMon (A B: ICMon.type) : + isICMon (hom A B) := isICMon.Build (hom A B) _ _. +Obligation 1. +eapply icmfunQ_isICAlg. +Qed. +Obligation 2. +eapply icmfunQ_isMon. +Qed. + +HB.instance Definition icmfunQ_isMonoid (A B: ICMon.type) : + isMon (hom A B) := icmfunQ_isMon A B. + +HB.instance Definition icmfunQ_isICAlgebra (A B: ICMon.type) : + isICAlg (hom A B) := icmfunQ_isICAlg A B. + +HB.instance Definition icmfunQ_isICMonoid (A B: ICMon.type) : + isICMon (hom A B) := icmfunQ_isICMon A B. + +Check ICMon.type : ICAlg_enriched_quiver.type. diff --git a/tests/enriched_cat_case6.v b/tests/enriched_cat_case6.v new file mode 100644 index 000000000..ff272ccd5 --- /dev/null +++ b/tests/enriched_cat_case6.v @@ -0,0 +1,510 @@ +From HB Require Import structures. +From Coq Require Import ssreflect ssrfun. + +(** Quiver *) + +HB.mixin Record isQuiver Obj := { hom : Obj -> Obj -> Type }. + +HB.structure Definition Quiver := { Obj of isQuiver Obj }. + + +(*************************************** OTHER MIXINS *************) +Require Import Coq.Program.Equality. +Require Import FunctionalExtensionality. + +HB.mixin Record isMagma T := { + mop : T -> T -> T; +}. +HB.structure Definition Magma := { T of isMagma T }. + +HB.mixin Record isMon T of isMagma T := { + munit : T; + massoc : associative (mop : T -> T -> T); + mlid : left_id munit mop; + mrid : right_id munit mop; + }. +#[verbose] +HB.structure Definition Mon := { T of isMon T }. + +HB.mixin Record isCAlg T of isMagma T := { + acomm : commutative (mop : T -> T -> T); + }. +#[verbose] +HB.structure Definition CAlg := { T of isCAlg T }. + +HB.mixin Record isIAlg T of isMagma T := { + aidem : idempotent (mop : T -> T -> T); + }. +#[verbose] +HB.structure Definition IAlg := { T of isIAlg T }. + +(* HB.mixin Record isICAlg T of isMagma T & IAlg T & CAlg T := { + }. *) +#[verbose] +HB.structure Definition ICAlg := { T of CAlg T & IAlg T }. + +(* HB.mixin Record isCMon T of isMagma T := { + cca: isCAlg T ; + cmon: isMon T; + }. *) +#[verbose] +HB.structure Definition CMon := { T of Mon T & CAlg T }. + +(* +HB.mixin Record isIMon T of isMagma T := { + iia: isIAlg T ; + imon: isMon T; + }. *) +#[verbose] +HB.structure Definition IMon := { T of Mon T & IAlg T }. + +(* +HB.mixin Record isICMon T of isMagma T := { + ica: isICAlg T ; + mon: isMon T; + }. +*) +#[verbose] +HB.structure Definition ICMon := { T of IMon T & CMon T }. + + +(***** wrapping ****************************************************) + +#[wrapper] +HB.mixin Record hom_isMagma T of Quiver T := + { hom_isMagma_private : forall A B, isMagma (@hom T A B) }. +HB.structure + Definition Magma_enriched_quiver := + { Obj of isQuiver Obj & hom_isMagma Obj }. + +(* +#[wrapper] +HB.mixin Record hom_isMon T of Quiver T := + { hom_isMon_private : forall A B, Mon (@hom T A B) }. +*) +(* need to add explicitly Magma_enriched_quiver, otherwise switch + from mixin to structure *) +#[wrapper] +HB.mixin Record hom_isMon T of Magma_enriched_quiver T := + { hom_isMon_private : forall A B, isMon (@hom T A B) }. +HB.structure + Definition Mon_enriched_quiver := + { Obj of isQuiver Obj & hom_isMon Obj }. + +#[wrapper] +HB.mixin Record hom_isCAlg T of Magma_enriched_quiver T := + { hom_isCAlg_private : forall A B, isCAlg (@hom T A B) }. +HB.structure + Definition CAlg_enriched_quiver := + { Obj of isQuiver Obj & hom_isCAlg Obj }. + +#[wrapper] +HB.mixin Record hom_isIAlg T of Magma_enriched_quiver T := + { hom_isIAlg_private : forall A B, isIAlg (@hom T A B) }. +HB.structure + Definition IAlg_enriched_quiver := + { Obj of isQuiver Obj & hom_isIAlg Obj }. + +(* +#[wrapper] +HB.mixin Record hom_isICAlg T of Magma_enriched_quiver T := + { hom_isICAlg_private : forall A B, isICAlg (@hom T A B) }. +HB.structure + Definition ICAlg_enriched_quiver := + { Obj of isQuiver Obj & hom_isICAlg Obj }. + +#[wrapper] +HB.mixin Record hom_isCMon T of Magma_enriched_quiver T := + { hom_isCMon_private : forall A B, isCMon (@hom T A B) }. +#[verbose] +HB.structure + Definition CMon_enriched_quiver := + { Obj of isQuiver Obj & hom_isCMon Obj }. + +#[wrapper] +HB.mixin Record hom_isIMon T of Magma_enriched_quiver T := + { hom_isIMon_private : forall A B, isIMon (@hom T A B) }. +*) +#[verbose] +HB.structure + Definition IMon_enriched_quiver := + { Obj of Mon_enriched_quiver Obj & IAlg_enriched_quiver Obj }. + +#[wrapper=false] +HB.instance Definition _ (T : IMon_enriched_quiver.type) A B : isMon (@hom T A B) := + Mon.on (@hom T A B). + +(****) + +#[verbose] +HB.structure + Definition CMon_enriched_quiver := + { Obj of Mon_enriched_quiver Obj & CAlg_enriched_quiver Obj }. + + +#[wrapper=false] +HB.instance Definition _ (T : CMon_enriched_quiver.type) A B := + Mon.on (@hom T A B). + +(* { Obj of isQuiver Obj & hom_isMon Obj & hom_isIAlg Obj }. *) + +(* +#[wrapper] +HB.mixin Record hom_isICMon T of Magma_enriched_quiver T := + { hom_isICMon_private : forall A B, isICMon (@hom T A B) }. +#[verbose] +HB.structure + Definition ICMon_enriched_quiver := + { Obj of isQuiver Obj & hom_isICMon Obj }. +*) + +(*** factory ********************************************************) + +HB.factory Record isMICAlg T of Mon T := { + amop : T -> T -> T; + ameq : forall x y, amop x y = mop x y; + amcomm : commutative amop; + amidem : idempotent amop; + }. + +HB.builders Context T (_ : isMICAlg T). + + Lemma amop_mop_eq : amop = mop. + (* destruct f; simpl. *) + eapply functional_extensionality; intro. + eapply functional_extensionality; intro. + apply ameq. + Qed. + + Definition dum_comm := + @eq_rect (T -> T -> T) amop (@commutative T T) amcomm mop amop_mop_eq. + + Definition dum_idem := + @eq_rect (T -> T -> T) amop (@idempotent T) amidem mop amop_mop_eq. + + HB.instance Definition b_C : isCAlg T := + isCAlg.Build T dum_comm. + + HB.instance Definition b_I : isIAlg T := + isIAlg.Build T dum_idem. + + (* + HB.instance Definition b_IC : isICAlg T := + isICAlg.Build T b_C b_I. + *) +(* + Lemma M : isMon T. + auto. + Qed. +*) + (* + HB.instance Definition b_M : isICMon T := + isICMon.Build T b_IC M. + *) + +HB.end. + +(*******************************************************************) + +(** INSTANCE 1 *********************************************** + +Object: Type, +Morphism: A -> option B +Structure: Monoid (from isMon) +*) + +HB.instance Definition funQ := isQuiver.Build Type + (fun A B => A -> option B). + +Check Type : Quiver.type. + +Definition funQ_comp {A B: Type} (f g: hom A B) : hom A B := + fun x => + match f x with + | Some _ => f x + | _ => g x end. + +Definition funQ_zero {A B: Type} : hom A B := + fun (_:A) => None. + +(* does not work without declaring the Magma wrapper *) +HB.instance Definition funQ_isMagma (A B: Type) : + isMagma (hom A B) := isMagma.Build _ funQ_comp. + +Program Definition funQ_isMon (A B: Type) : isMon (hom A B) := + isMon.Build _ funQ_zero _ _ _. +Obligation 1. + unfold associative; intros. + eapply functional_extensionality; intro a. + unfold mop; simpl. + unfold funQ_comp. + destruct (x a) eqn:K1. + simpl; auto. + destruct (y a); auto. +Qed. +Obligation 2. + unfold left_id; intros. + unfold funQ_comp; auto. +Qed. +Obligation 3. + unfold right_id, mop; simpl; intros. + unfold funQ_zero, funQ_comp; simpl. + eapply functional_extensionality; intro a. + destruct (x a); auto. +Qed. + +Program Definition funQ_isIAlg (A B: Type) : + isIAlg (hom A B) := isIAlg.Build _ _. +Obligation 1. +unfold idempotent; intros. +eapply functional_extensionality; intro a. +unfold mop; simpl. +unfold funQ_comp; simpl. +destruct (x a); auto. +Qed. + +(* +Program Definition funQ_isIMon (A B: Type) : + isIMon (hom A B) := isIMon.Build (hom A B) _ _. +Obligation 1. +eapply funQ_isIAlg. +Qed. +Obligation 2. +eapply funQ_isMon. +Qed. +*) + +#[verbose] +HB.instance Definition funQ_IAlgebra (A B: Type) : + isIAlg (hom A B) := funQ_isIAlg A B. + +#[verbose] +HB.instance Definition funQ_Monoid (A B: Type) : + isMon (hom A B) := funQ_isMon A B. + +Check hom (nat:Type) nat : IMon.type. + +(***) + +HB.graph "foo.dot". + +Definition hom' (A B: Type) := hom A B. + +HB.instance Definition _ (A B: Type) := Mon.on (hom' A B). +HB.instance Definition _ (A B: Type) := IAlg.on (hom' A B). + +Check hom' (nat:Type) nat : IMon.type. + +HB.instance Definition _ (A B: Type) := Mon.on (hom' A B). + + +(** INSTANCE 2 ********************************************** + +Object: CMon.type +Morphism: CMon.sort A -> CMon.sort B +Structure: commutative monoid (by CMon) +*) + +#[verbose] +HB.instance Definition cmfunQ := + isQuiver.Build CMon.type + (fun A B => (CMon.sort A) -> (CMon.sort B)). + +Definition cmfunQ_comp {A B: CMon.type} (f g: hom A B) : hom A B := + fun x => @mop B (f x) (g x). + +Definition cmfunQ_zero {A B: CMon.type} : hom A B := fun a : A => munit. + +(* does not work without declaring the Magma wrapper *) +HB.instance Definition cmfunQ_isMagma (A B: CMon.type) : + isMagma (hom A B) := isMagma.Build _ cmfunQ_comp. + +(* does not type-check without the Magma instance *) +Program Definition cmfunQ_isMon (A B: CMon.type) : + isMon (hom A B) := isMon.Build (hom A B) cmfunQ_zero _ _ _. +Obligation 1. +unfold associative, mop; simpl; intros. +unfold cmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +refine (massoc _ _ _). +Qed. +Obligation 2. +unfold left_id, mop; simpl; intros. +unfold cmfunQ_comp, cmfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +refine (mlid _). +Qed. +Obligation 3. +unfold right_id, mop; simpl; intros. +unfold cmfunQ_comp, cmfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +refine (mrid _). +Qed. + +Program Definition cmfunQ_isCAlg (A B: CMon.type) : + isCAlg (hom A B) := isCAlg.Build (hom A B) _. +Obligation 1. +unfold commutative, mop; simpl; intros. +unfold cmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +refine (acomm _ _). +Qed. + +HB.instance Definition cmfunQ_isMonoid (A B: CMon.type) : + isMon (hom A B) := cmfunQ_isMon A B. + +HB.instance Definition cmfunQ_isICAlgebra (A B: CMon.type) : + isCAlg (hom A B) := cmfunQ_isCAlg A B. + +(* +HB.instance Definition icmfunQ_isCMonoid (A B: CMon.type) : + isCMon (hom A B) := cmfunQ_isCMon A B. + +Check CMon.type : CAlg_enriched_quiver.type. +*) + +(*********************************************************) + +(* +Object: IMon.type +Morphism: IMon.sort A -> IMon.sort B +Structure: idempotent monoid (by IMon) +*) + +#[verbose] +HB.instance Definition imfunQ := + isQuiver.Build IMon.type + (fun A B => (IMon.sort A) -> (IMon.sort B)). + +Definition imfunQ_comp {A B: IMon.type} (f g: hom A B) : hom A B := + fun x => @mop B (f x) (g x). + +Definition imfunQ_zero {A B: IMon.type} : hom A B := fun a : A => munit. + +(* does not work without declaring the Magma wrapper *) +HB.instance Definition imfunQ_isMagma (A B: IMon.type) : + isMagma (hom A B) := isMagma.Build _ imfunQ_comp. + +(* does not type-check without the Magma instance *) +Program Definition imfunQ_isMon (A B: IMon.type) : + isMon (hom A B) := isMon.Build (hom A B) imfunQ_zero _ _ _. +Obligation 1. +unfold associative, mop; simpl; intros. +unfold imfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +refine (massoc _ _ _). +Qed. +Obligation 2. +unfold left_id, mop; simpl; intros. +unfold imfunQ_comp, imfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +refine (mlid _). +Qed. +Obligation 3. +unfold right_id, mop; simpl; intros. +unfold imfunQ_comp, imfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +refine (mrid _). +Qed. + +Program Definition imfunQ_isIAlg (A B: IMon.type) : + isIAlg (hom A B) := isIAlg.Build (hom A B) _. +Obligation 1. +unfold idempotent, mop; simpl; intros. +unfold imfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +refine (aidem _). +Qed. + +HB.instance Definition imfunQ_isMonoid (A B: IMon.type) : + isMon (hom A B) := imfunQ_isMon A B. + +HB.instance Definition imfunQ_isIAlgebra (A B: IMon.type) : + isIAlg (hom A B) := imfunQ_isIAlg A B. + +Check IMon.type : IAlg_enriched_quiver.type. + +(*********************************************************) +(* +Object: ICMon.type +Morphism: ICMon.sort A -> ICMon.sort B +Structure: idempotent commutative monoid (by ICMon) +*) + +#[verbose] +HB.instance Definition icmfunQ := + isQuiver.Build ICMon.type + (fun A B => (ICMon.sort A) -> (ICMon.sort B)). + +Definition icmfunQ_comp {A B: ICMon.type} (f g: hom A B) : hom A B := + fun x => @mop B (f x) (g x). + +Definition icmfunQ_zero {A B: ICMon.type} : hom A B := fun a : A => munit. + +(* does not work without declaring the Magma wrapper *) +HB.instance Definition icmfunQ_isMagma (A B: ICMon.type) : + isMagma (hom A B) := isMagma.Build _ icmfunQ_comp. + +(* does not type-check without the Magma instance *) +Program Definition icmfunQ_isMon (A B: ICMon.type) : + isMon (hom A B) := isMon.Build (hom A B) icmfunQ_zero _ _ _. +Obligation 1. +unfold associative, mop; simpl; intros. +unfold icmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +refine (massoc _ _ _). +Qed. +Obligation 2. +unfold left_id, mop; simpl; intros. +unfold icmfunQ_comp, icmfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +refine (mlid _). +Qed. +Obligation 3. +unfold right_id, mop; simpl; intros. +unfold icmfunQ_comp, icmfunQ_zero; simpl; intros. +eapply functional_extensionality; intro x0. +refine (mrid _). +Qed. + +(* Program Definition icmfunQ_isICAlg (A B: ICMon.type) : + isICAlg (hom A B) := isICAlg.Build (hom A B) _ _. +Obligation 1. +econstructor. +unfold commutative, mop; simpl; intros. +unfold icmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isICMon_mixin. +simpl in *. +destruct ica0. +destruct isca0. +eapply acomm0; auto. +Qed. +Obligation 2. +econstructor. +unfold idempotent, mop; simpl; intros. +unfold icmfunQ_comp; simpl; intros. +eapply functional_extensionality; intro x0. +destruct B. +destruct class. +destruct enriched_cat_case1_isICMon_mixin. +simpl in *. +destruct ica0. +destruct isia0. +eapply aidem0; auto. +Qed. *) + +(* Program Definition icmfunQ_isICMon (A B: ICMon.type) : + isICMon (hom A B) := isICMon.Build (hom A B) _ _. +Obligation 1. +eapply icmfunQ_isICAlg. +Qed. +Obligation 2. +eapply icmfunQ_isMon. +Qed. *) + +HB.instance Definition icmfunQ_isMonoid (A B: ICMon.type) : + isMon (hom A B) := icmfunQ_isMon A B. + diff --git a/tests/hnf.v b/tests/hnf.v index b219a6a82..c95694848 100644 --- a/tests/hnf.v +++ b/tests/hnf.v @@ -14,5 +14,5 @@ Print HB_unnamed_mixin_8. HB.instance Definition _ := f.Build bool (3 + 2). Print Datatypes_bool__canonical__hnf_S. -Print HB_unnamed_mixin_12. +(* Print HB_unnamed_mixin_12. *) diff --git a/tests/hnf.v.out b/tests/hnf.v.out index b35edbc76..f94f1ac4b 100644 --- a/tests/hnf.v.out +++ b/tests/hnf.v.out @@ -5,8 +5,5 @@ HB_unnamed_mixin_8 = {| M.x := f.y nat HB_unnamed_factory_6 + 1 |} : M.axioms_ nat Datatypes_bool__canonical__hnf_S = -{| S.sort := bool; S.class := {| S.hnf_M_mixin := HB_unnamed_mixin_12 |} |} +{| S.sort := bool; S.class := {| S.hnf_M_mixin := hnf_f__to__hnf_M__11 |} |} : S.type -HB_unnamed_mixin_12 = -Builders_1.HB_unnamed_factory_3 bool HB_unnamed_factory_9 - : M.axioms_ bool diff --git a/tests/monoid_enriched_cat.v b/tests/monoid_enriched_cat.v new file mode 100644 index 000000000..95b935089 --- /dev/null +++ b/tests/monoid_enriched_cat.v @@ -0,0 +1,485 @@ +From HB Require Import structures. +From Coq Require Import ssreflect ssrfun. + + +Require Import FunctionalExtensionality. + +Module NoParams. + +HB.mixin Record isQuiver Obj := { hom : Obj -> Obj -> Type }. + +HB.structure Definition Quiver := { Obj of isQuiver Obj }. + +HB.mixin Record isMon A := { + zero : A; + add : A -> A -> A; + addrA : associative add; + add0r : left_id zero add; + addr0 : right_id zero add; + }. + +HB.structure + Definition Monoid := { A of isMon A }. + +(* This is expected to fail, as it isn't a mixin *) +Fail HB.structure + Definition Monoid_enriched_quiver := + { Obj of isQuiver Obj & + (forall A B : Obj, isMon (@hom (Quiver.clone Obj _) A B)) }. + +(* About zero. + Print zero. +*) +(* Step 0: define a wrapper predicate in coq-elpi *) +(* 5 lines of documentation + 1 line of elpi code in structure.v + `pred wrapper-mixin o:mixinname, o:gref, o:mixinname` +*) +(* Step 1: add a wrapper attribute to declare wrappers, + they should index: + - the wrapped mixin (`isMon`) + - the wrapper mixin (`hom_isMon`) + - the new subject (`hom`) + This attribute will add an entry in the `wrapper-mixin` database. + As an addition substep, we should check that the wrapper has + exactly one field, which is the wrapped mixin. + *) +(* added wrapper attribute in utils.elpi. + added pred wrapper-mixin in structures.v. + added conditional rule for wrapper-mixin in factory.elpi. +*) +#[wrapper] +HB.mixin Record hom_isMon T of Quiver T := + { hom_isMon_private : forall A B, isMon (@hom T A B) }. + +Succeed HB.structure + Definition Monoid_enriched_quiver := + { Obj of isQuiver Obj & + (forall A B : Obj, isMon (@hom _ A B)) }. + +Succeed HB.structure + Definition Monoid_enriched_quiver := + { Obj of (*isQuiver Obj & once we wrap we pull this in as a dep! *) + (forall A B : Obj, isMon (hom A B)) }. + + (* which one is best? *) +Succeed HB.structure + Definition Monoid_enriched_quiver := + { Obj of isQuiver Obj & + (forall A B : Obj, isMon (@hom (Quiver.clone Obj _) A B)) }. + +HB.structure + Definition Monoid_enriched_quiver := + { Obj of isQuiver Obj & + (forall A B (* : Quiver.sort _ *), isMon (hom A B)) }. + + +(* Print Canonical Projections. *) +(* About hom_isMon.hom_isMon_private. *) +(* About hom_isMon_private. *) + +(* Step 2: at structure declaration, export the main and only projection + of each declared wrapper as an instance of the wrapped structure on + its subject +#[verbose] HB.structure + Definition Monoid_enriched_quiver := + { Obj of isQuiver Obj & hom_isMon Obj }. + *) + +(* About hom_isMon.hom_isMon_private. *) +(* About hom_isMon_private. *) + +(* as expected from step 2, now this instance declaration is no more necessay *) +(* + HB.instance Definition _ (T : Monoid_enriched_quiver.type) (A B : T) : isMon (@hom T A B) := + @hom_isMon_private T A B. +*) +(* each instance of isMon should be tried as an instance of hom_isMon *) +(* + (* Step 3: for each instance of a wrapped mixin on a subject known + to be wrapped, automatically produce an instance of the wrapper mixin too. *) + HB.instance Definition _ := isQuiver.Build Type (fun A B => A -> B). + Fail HB.instance Definition homTypeMon (A B : Quiver.type) := isMon.Build (hom A B) (* ... *). + (* This last command should create a `Monoid_enriched_quiver`, in order to do so it should + automatically instanciate the wrapper `hom_isMon`: + HB.instance Definition _ := hom_isMon.Build Type homTypeMon. + *) +*) + +(* Essentially, step 2 is the elimination rule for the wrapper, step 3 is the introduction one *) + +(* quiver instance (simply typed functions between two types) *) +(* Elpi Trace Browser. *) + +HB.instance Definition funQ := isQuiver.Build Type + (fun A B => A -> option B). + +(* Print Canonical Projections. *) + +(* prove that for every two types the quiver is a monoid *) + + +Definition funQ_comp {A B} (f g: A -> option B) (x: A) : option B := + match f x with + | Some _ => f x + | _ => g x end. + + (* + Program Definition funQ_isMonF_alt (A B: Type) : isMon (hom A B) := + isMon.Build (A -> option B) (fun (_:A) => None) funQ_comp _ _ _. + Obligations. + Obligation 1. + unfold associative; intros. + eapply functional_extensionality; intro a. + unfold funQ_comp. + destruct (x a) eqn:K1. + simpl; auto. + destruct (y a); auto. + Qed. + Obligation 2. + unfold left_id; intros. + unfold funQ_comp; auto. + Qed. + Obligation 3. + unfold right_id; intros. + eapply functional_extensionality; intro a. + unfold funQ_comp. + destruct (x a); auto. + Qed. +*) + +Program Definition funQ_isMonF (A B: Type) : isMon (A -> option B) := + isMon.Build (A -> option B) (fun (_:A) => None) funQ_comp _ _ _. +(* Obligations. *) +Obligation 1. +unfold associative; intros. +eapply functional_extensionality; intro a. +unfold funQ_comp. +destruct (x a) eqn:K1. +simpl; auto. +destruct (y a); auto. +Qed. +Obligation 2. +unfold left_id; intros. +unfold funQ_comp; auto. +Qed. +Obligation 3. +unfold right_id; intros. +eapply functional_extensionality; intro a. +unfold funQ_comp. +destruct (x a); auto. +Qed. + +(* +Print Canonical Projections. +*) + + +Fail Check (nat -> option nat) : Monoid.type. + + +(* use the lemma to instantiate isMon. Notice the genericity of the type. + In principle this instance should be derivable from the wrapper instance. + But since we haven't introduced the wrapper instance yet, we use this + HB command to actually introduce it. *) + +Check Type : Quiver.type. +Fail Check Type : Monoid_enriched_quiver.type. + +#[verbose] HB.instance Definition funQ_isMon (A B: Type) : isMon (hom A B) := + funQ_isMonF A B. + +Check Type : Monoid_enriched_quiver.type. + +Section A0. +#[verbose, log] +HB.declare Context T of Monoid_enriched_quiver T. + +Goal forall A B : T, isMon (hom A B). +assumption. +Qed. + +End A0. + +End NoParams. + + +(******************* PARAMETERS ***********************) + +Module WithParams. + + + +HB.mixin Record isQuiver P Obj := { hom : Obj -> Obj -> Type; embed : P -> Obj; }. + +HB.structure Definition Quiver P := { Obj of isQuiver P Obj }. + +HB.mixin Record isMon S A := { + zero : A; + add : A -> A -> A; + scale : S -> A -> A; + addrA : associative add; + add0r : left_id zero add; + addr0 : right_id zero add; + }. + +HB.structure + Definition Monoid S := { A of isMon S A }. + +(* This is expected to fail, as it isn't a mixin *) +Fail HB.structure + Definition Monoid_enriched_quiver P S := + { Obj of isQuiver P Obj & + (forall A B : Obj, isMon S (@hom (Quiver.clone Obj _) A B)) }. + +#[wrapper] +HB.mixin Record hom_isMon P S T of Quiver P T := + { hom_isMon_private : forall A B, isMon S (@hom P T A B) }. + +#[verbose] HB.structure + Definition Monoid_enriched_quiver P S := + { Obj of isQuiver P Obj & hom_isMon P S Obj }. + +HB.instance Definition funQ := isQuiver.Build nat Type + (fun A B => A -> option B) (fun x => match x with O => nat | S _ => bool end). + +Definition funQ_comp {A B} (f g: A -> option B) (x: A) : option B := + match f x with + | Some _ => f x + | _ => g x end. + +Program Definition funQ_isMonF S (A B: Type) : isMon S (A -> option B) := + isMon.Build S (A -> option B) (fun (_:A) => None) funQ_comp (fun _ x => x) _ _ _. +(* Obligations. *) +Obligation 1. +unfold associative; intros. +eapply functional_extensionality; intro a. +unfold funQ_comp. +destruct (x a) eqn:K1. +simpl; auto. +destruct (y a); auto. +Qed. +Obligation 2. +unfold left_id; intros. +unfold funQ_comp; auto. +Qed. +Obligation 3. +unfold right_id; intros. +eapply functional_extensionality; intro a. +unfold funQ_comp. +destruct (x a); auto. +Qed. + +Fail Check (nat -> option nat) : Monoid.type _. + + +(* use the lemma to instantiate isMon. Notice the genericity of the type. + In principle this instance should be derivable from the wrapper instance. + But since we haven't introduced the wrapper instance yet, we use this + HB command to actually introduce it. *) + +Check Type : Quiver.type _. +Fail Check Type : Monoid_enriched_quiver.type _ _. + +(* What should we do *) +Fail #[verbose] HB.instance Definition funQ_isMon S (A B: Type) : isMon S (hom A B) := + funQ_isMonF S A B. + +#[verbose] HB.instance Definition funQ_isMon (A B: Type) : isMon bool (hom A B) := + funQ_isMonF bool A B. + +Check Type : Monoid_enriched_quiver.type _ _. + + +End WithParams. + + + + + + + + + + + + + + + + + + + + + +(* BUG + +HB.mixin Record isNE T := { def: T }. +HB.structure Definition NE := { T of isNE T }. + +HB.factory Record dummy T of Monoid_enriched_quiver T := { x : T }. + +HB.builders Context T (f : dummy T). + +Goal forall A B : T, isMon (hom A B). +assumption. +Qed. + +HB.instance Definition _ := isNE.Build T x. + +HB.end. + +This builder is not a legit one!!!!! +About Builders_25.local_mixin_monoid_enriched_cat_hom_isMon. + +About wrapped__20. +#[verbose] HB.instance +Definition x := dummy.Build Type nat. +*) + +(* Check (fun A B : Type => hom A B : Monoid.type). *) + +(* instantiate hom_isMon by using the generic isMon instance to define 'private' *) +(* HB.instance Definition funQ_hom_isMon := + hom_isMon.Build Type funQ_isMonF. + *) + +(* Print Canonical Projections. *) + +(* Check (fun A B : Type => hom A B : Monoid.type). *) + +(* HB.about private. *) +(* Print Canonical Projections. *) +(* this has to be changed, it should be something like (hom nat nat): + Check (nat -> option nat) : Monoid.type. *) +(* +HB.about funQ_isMonF. +Fail HB.about funQ_hom_isMon. +About funQ_hom_isMon. +*) + +Elpi Print HB.structure. + + +(**************************************************************) +(* Elpi code moved to factory.elpi *) +(* +Elpi Command x. +Elpi Accumulate File "HB/common/stdpp.elpi". +Elpi Accumulate File "HB/common/database.elpi". +Elpi Accumulate File "HB/common/utils.elpi". +Elpi Accumulate File "HB/status.elpi". +Elpi Accumulate Db hb.db. + +(* extracts isMon *) +Elpi Accumulate lp:{{ + +pred extract_ret_type_name i:term, o:gref. +extract_ret_type_name (prod _ _ TF) Out1 :- + pi p\ + extract_ret_type_name (TF p) Out1. +extract_ret_type_name Ty GR1 :- + Ty = app [global GR0| _], + factory-alias->gref GR0 GR1. + +pred extract_wrapped1 i:indt-decl, o:gref. +extract_wrapped1 (parameter ID _ _ R) Out :- + pi p\ + extract_wrapped1 (R p) Out. +extract_wrapped1 (record ID _ KID (field _ _ Ty (x\end-record))) GR0 :- + extract_ret_type_name Ty GR0. + +}}. +Elpi Typecheck. + +(* extracts hom *) +Elpi Accumulate lp:{{ + +pred extract_inner_type_name i:term, o:gref. +extract_inner_type_name (prod _ _ TF) Out1 :- + pi p\ + extract_inner_type_name (TF p) Out1. +extract_inner_type_name Ty Gr :- + Ty = (app [global _, app [global Gr| _]]). + +pred extract_subject1 i:indt-decl, o:gref. +extract_subject1 (parameter ID _ _ R) Out :- + pi p\ + extract_subject1 (R p) Out. +extract_subject1 (record ID _ KID (field _ _ Ty (x\end-record))) GR0 :- + extract_inner_type_name Ty GR0. + +}}. +Elpi Typecheck. + +(* better version, with predicate parameters *) +Elpi Accumulate lp:{{ + +pred extract_from_record_decl i: (term -> gref -> prop), i:indt-decl, o:gref. +extract_from_record_decl P (parameter ID _ _ R) Out :- + pi p\ + extract_from_record_decl P (R p) Out. +extract_from_record_decl P (record ID _ KID (field _ _ Ty (x\end-record))) GR0 :- + P Ty GR0. + +pred extract_from_rtty i: (term -> gref -> prop), i: term, o:gref. +extract_from_rtty P (prod _ _ TF) Out1 :- + pi p\ + extract_from_rtty P (TF p) Out1. +extract_from_rtty P Ty Gr :- P Ty Gr. + +pred xtr_fst_op i:term, o:gref. +xtr_fst_op Ty Gr1 :- + Ty = (app [global Gr0| _]), + factory-alias->gref Gr0 Gr1. + +pred xtr_snd_op i:term, o:gref. +xtr_snd_op Ty Gr :- + Ty = (app [global _, app [global Gr| _]]). + +pred extract_wrapped i:indt-decl, o:gref. +extract_wrapped In Out :- + extract_from_record_decl (extract_from_rtty xtr_fst_op) In Out. + +pred extract_subject i:indt-decl, o:gref. +extract_subject In Out :- + extract_from_record_decl (extract_from_rtty xtr_snd_op) In Out. + +pred wrapper_mixin_aux i:gref, o:gref, o:gref. +wrapper_mixin_aux XX Gr1 Gr2 :- + XX = (indt I), + coq.env.indt-decl I D, + extract_subject D Gr1, + extract_wrapped D Gr2. + +}}. +Elpi Typecheck. + +(*for debugging - check /tmp/traced.tmp.json with Elpi Tracer *) +(* Elpi Trace Browser. *) +(* Elpi Bound Steps 1000. *) + +(* OK *) +Elpi Query lp:{{ + + coq.locate "hom_isMon.axioms_" XX, + wrapper_mixin_aux XX Gr1 Gr2. + +}}. + +(* also OK *) +Elpi Query lp:{{ + + coq.locate "hom_isMon.axioms_" XX, + XX = (indt I), + coq.env.indt-decl I D, + extract_wrapped1 D GR11, + extract_subject1 D GR12. + +}}. + +Elpi Print HB.structure. + +stop. +*) + diff --git a/tests/not_same_key.v.out b/tests/not_same_key.v.out index b04461f4c..218208749 100644 --- a/tests/not_same_key.v.out +++ b/tests/not_same_key.v.out @@ -1,2 +1,3 @@ The command has indeed failed with message: -HB: all mixins must have the same key +HB: expecting a factory on T +or a factory on a structure operation or tag. Got: B.phant_axioms T T1 diff --git a/tests/tag_wrap.v b/tests/tag_wrap.v new file mode 100644 index 000000000..deafbccf6 --- /dev/null +++ b/tests/tag_wrap.v @@ -0,0 +1,38 @@ +From HB Require Import structures. + +HB.mixin Record isSomething T := { clearly : True }. +HB.structure Definition Something := { T of isSomething T }. + +HB.mixin Record isTerminal (T : Type) := { p : True }. + +HB.tag Definition this_one (T : Something.type) : Type := T. + +#[wrapper] +HB.mixin Record this_one_isTerminal T of Something T := { + private : isTerminal (this_one T) +}. + +HB.tag Definition this_other_one (T : Something.type) : Type := T. + +#[wrapper] +HB.mixin Record this_other_one_isTerminal T of Something T := { + private : isTerminal (this_other_one T) +}. +(* This is a bug, maybe even in master. If I declare an instance on a mixin + which leads to no new structure instance, then the mixin is not use later + on *) +HB.structure Definition magic1 := { T of + isSomething T & + isTerminal (this_one T) +}. + +HB.structure Definition magic := { T of + isSomething T & + isTerminal (this_one T) & + isTerminal (this_other_one T) +}. + +HB.instance Definition _ : isSomething nat := isSomething.Build nat I. +HB.instance Definition _ : isTerminal (this_one nat) := isTerminal.Build nat I. +HB.instance Definition _ : isTerminal (this_other_one nat) := isTerminal.Build nat I. +Check nat : magic.type. diff --git a/theories/algebra.v b/theories/algebra.v new file mode 100644 index 000000000..9eada670d --- /dev/null +++ b/theories/algebra.v @@ -0,0 +1,122 @@ +Require Import ssreflect ssrfun. +Unset Universe Checking. +From HB Require Import structures cat. +Set Universe Checking. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. +Add Search Blacklist "__canonical__". + +Local Open Scope algebra_scope. +Local Open Scope cat_scope. + +HB.mixin Record IsRing A := { + zero : A; + one : A; + add : A -> A -> A; + opp : A -> A; + mul : A -> A -> A; + addrA : associative add; + addrC : commutative add; + add0r : left_id zero add; + addNr : left_inverse zero opp add; + mulrA : associative mul; + mul1r : left_id one mul; + mulr1 : right_id one mul; + mulrDl : left_distributive mul add; + mulrDr : right_distributive mul add; +}. + +#[short(type="ring")] +HB.structure Definition Ring := { A of IsRing A }. + +Bind Scope algebra_scope with Ring.sort. +Notation "0" := zero : algebra_scope. +Notation "1" := one : algebra_scope. +Infix "+" := (@add _) : algebra_scope. +Notation "- x" := (@opp _ x) : algebra_scope. +Infix "*" := (@mul _) : algebra_scope. +Notation "x - y" := (x + - y) : algebra_scope. + +Lemma addr0 (R : ring) : right_id (@zero R) add. +Proof. by move=> x; rewrite addrC add0r. Qed. + +Lemma addrN (R : ring) : right_inverse (@zero R) opp add. +Proof. by move=> x; rewrite addrC addNr. Qed. + +Lemma addKr (R : ring) (x : R) : cancel (add x) (add (- x)). +Proof. by move=> y; rewrite addrA addNr add0r. Qed. + +Lemma addrI (R : ring) (x : R) : injective (add x). +Proof. exact: can_inj (addKr _). Qed. + +Lemma opprK (R : ring) : involutive (@opp R). +Proof. by move=> x; apply: (@addrI _ (- x)); rewrite addNr addrN. Qed. + +HB.mixin Record IsRingHom (A B : ring) (f : A -> B) := { + hom1_subproof : f 1%A = 1%A; + homB_subproof : {morph f : x y / x - y}; + homM_subproof : {morph f : x y / (x * y)%A}; +}. + +HB.structure Definition RingHom A B := { f of IsRingHom A B f }. + +Lemma id_IsRingHom A : IsRingHom A A idfun. Proof. by []. Defined. +HB.instance Definition _ A := id_IsRingHom A. + +Lemma comp_IsRingHom (A B C : ring) + (f : RingHom.type A B) (g : RingHom.type B C) : + IsRingHom A C (f \; g :> U). +Proof. +by constructor => [|x y|x y]; +rewrite /comp/= ?hom1_subproof ?homB_subproof ?homM_subproof. +Qed. +HB.instance Definition _ A B C f g := @comp_IsRingHom A B C f g. + +HB.instance Definition _ := IsQuiver.Build ring RingHom.type. +HB.instance Definition _ := + Quiver_IsPreCat.Build ring (fun _ => idfun) (fun _ _ _ f g => f \; g :> U). +HB.instance Definition _ := Quiver_IsPreConcrete.Build ring (fun _ _ => id). +Lemma ring_precat : PreConcrete_IsConcrete ring. +Proof. +constructor => A B [f cf] [g cg]//=; rewrite -[_ = _]/(f = g) => fg. +case: _ / fg in cg *; congr {|RingHom.sort := _ ; RingHom.class := _|}. +case: cf cg => [[? ? ?]] [[? ? ?]]. +by congr RingHom.Class; congr IsRingHom.phant_Build => //=; apply: Prop_irrelevance. +Qed. +HB.instance Definition _ := ring_precat. + +Lemma ring_IsCat : PreCat_IsCat ring. +Proof. +by constructor=> [A B f|A B f|A B C D f g h]; exact: concrete_fun_inj. +Qed. +HB.instance Definition _ := ring_IsCat. + +Lemma hom1 (R S : ring) (f : R ~> S) : f 1%A = 1%A. +Proof. exact: hom1_subproof. Qed. +Lemma homB (R S : ring) (f : R ~> S) : {morph f : x y / x - y}. +Proof. exact: homB_subproof. Qed. +Lemma homM (R S : ring) (f : R ~> S) : {morph f : x y / (x * y)%A}. +Proof. exact: homM_subproof. Qed. +Lemma hom0 (R S : ring) (f : R ~> S) : f 0%A = 0%A. +Proof. by rewrite -(addrN 1%A) homB addrN. Qed. +Lemma homN (R S : ring) (f : R ~> S) : {morph f : x / - x}. +Proof. by move=> x; rewrite -[- x]add0r homB hom0 add0r. Qed. +Lemma homD (R S : ring) (f : R ~> S) : {morph f : x y / x + y}. +Proof. by move=> x y; rewrite -[y]opprK !homB !homN. Qed. + +HB.mixin Record IsIdeal (R : ring) (I : R -> Prop) := { + ideal0 : I 0; + idealD : forall x y, I x -> I y -> I (x + y); + idealM : forall x y, I y -> I (x * y)%A; +}. +HB.structure Definition Ideal (R : ring) := { I of IsIdeal R I }. + +HB.mixin Record Ideal_IsPrime (R : ring) (I : R -> Prop) of IsIdeal R I := { + ideal_prime : forall x y : R, I (x * y)%A -> I x \/ I y +}. +#[short(type="spectrum")] +HB.structure Definition PrimeIdeal (R : ring) := + { I of Ideal_IsPrime R I & Ideal R I }. + diff --git a/examples/cat/cat.v b/theories/cat.v similarity index 63% rename from examples/cat/cat.v rename to theories/cat.v index f340cd457..81a248147 100644 --- a/examples/cat/cat.v +++ b/theories/cat.v @@ -317,9 +317,10 @@ HB.instance Definition _ {C D : cat} (c : C) := (* opposite category *) Definition catop (C : U) : U := C. -Notation "C ^op" := (catop C) (at level 10, format "C ^op") : cat_scope. +Notation "C ^op" := (catop C) + (at level 2, format "C ^op") : cat_scope. HB.instance Definition _ (C : quiver) := - IsQuiver.Build (C^op) (fun a b => hom b a). + IsQuiver.Build C^op (fun a b => hom b a). HB.instance Definition _ (C : precat) := Quiver_IsPreCat.Build (C^op) (fun=> idmap) (fun _ _ _ f g => g \; f). HB.instance Definition _ (C : cat) := PreCat_IsCat.Build (C^op) @@ -399,20 +400,23 @@ Qed. HB.instance Definition _ := prod_is_cat. End cat_prod. +HB.instance Definition _ (C : U) (D : quiver) := + IsQuiver.Build (C -> D) (fun f g => forall c, f c ~> g c). + (* naturality *) -HB.mixin Record IsNatural (C D : precat) (F G : C ~>_quiver D) +HB.mixin Record IsNatural (C : quiver) (D : precat) (F G : C ~>_quiver D) (n : forall c, F c ~> G c) := { natural : forall (a b : C) (f : a ~> b), F <$> f \; n b = n a \; G <$> f }. Unset Universe Checking. -HB.structure Definition Natural (C D : precat) +HB.structure Definition Natural (C : quiver) (D : precat) (F G : C ~>_quiver D) : Set := { n of @IsNatural C D F G n }. Set Universe Checking. -HB.instance Definition _ (C D : precat) := +HB.instance Definition _ (C : quiver) (D : precat) := IsQuiver.Build (PreFunctor.type C D) (@Natural.type C D). -HB.instance Definition _ (C D : cat) := +HB.instance Definition _ (C D : precat) := IsQuiver.Build (Functor.type C D) (@Natural.type C D). Arguments natural {C D F G} n [a b] f : rename. @@ -489,41 +493,68 @@ constructor => [F G f|F G f|F G H J f g h]. Qed. HB.instance Definition _ C D := @functor_cat C D. -Section nat_map_left. -Context {C D E : precat} {F G : C ~> D}. +Lemma idFmap (C : cat) (a b : C) (f : a ~> b) : idfun <$> f = f. +Proof. by []. Qed. -Definition nat_lmap (H : D ~>_quiver E) (n : forall c, F c ~> G c) : - forall c, (H \o F)%FUN c ~> (H \o G)%FUN c := fun c => H <$> n c. +Lemma compFmap (C D E : cat) (F : C ~> D) (G : D ~> E) (a b : C) (f : a ~> b) : + (G \o F) <$> f = G <$> F <$> f. +Proof. by []. Qed. -Fail Check fun (H : D ~> E) (n : F ~~> G) => nat_lmap H n : H \o F ~~> H \o G. +Section left_whiskering. +Context {C D E : precat} {F G : C ~> D}. -Lemma nat_lmap_is_natural (H : D ~> E) (n : F ~~> G) : - IsNatural C E (H \o F) (H \o G) (nat_lmap H n). -Proof. by constructor=> a b f; rewrite /nat_lmap/= -!Fcomp natural. Qed. -HB.instance Definition _ H n := nat_lmap_is_natural H n. +Definition whiskerl_fun (eta : forall c, F c ~> G c) (H : D ~> E) : + forall c, (F \; H) c ~> (G \; H) c := fun c => H <$> eta c. -Check fun (H : D ~> E) (n : F ~~> G) => nat_lmap H n : H \o F ~~> H \o G. +Lemma whiskerl_is_nat (eta : F ~> G) (H : D ~> E) : + IsNatural _ _ _ _ (whiskerl_fun eta H). +Proof. by constructor=> a b f; rewrite /whiskerl_fun/= -!Fcomp natural. Qed. -End nat_map_left. +HB.instance Definition _ (eta : F ~> G) (H : D ~> E) := whiskerl_is_nat eta H. +Definition whiskerl (eta : F ~> G) (H : D ~> E) : (F \; H) ~> (G \; H) := + whiskerl_fun eta H : Natural.type _ _. +End left_whiskering. -Notation "F n" := (nat_lmap F n) +Notation "F n" := (whiskerl F n) (at level 58, format "F n", right associativity) : cat_scope. -Section nat_map_right. -Context {C D E : precat} {F G : C ~> D}. +Section right_whiskering. +Context {C D E : precat} {F G : D ~> E}. + +Definition whiskerr_fun (H : C ~> D) (eta : forall d, F d ~> G d) + (c : C) : (H \; F) c ~> (H \; G) c := eta (H c). -Definition nat_rmap (H : E -> C) (n : forall c, F c ~> G c) : - forall c, (F \o H)%FUN c ~> (G \o H)%FUN c := fun c => n (H c). -Lemma nat_rmap_is_natural (H : E ~> C :> quiver) (n : F ~~> G) : - IsNatural E D (F \o H)%FUN (G \o H)%FUN (nat_rmap H n). -Proof. by constructor=> a b f; rewrite /nat_lmap/= natural. Qed. -HB.instance Definition _ H n := nat_rmap_is_natural H n. +Lemma whiskerr_is_nat (H : C ~> D) (eta : F ~> G) : + IsNatural _ _ _ _ (whiskerr_fun H eta). +Proof. by constructor=> a b f; rewrite /whiskerr_fun/= natural. Qed. +HB.instance Definition _ (H : C ~> D) (eta : F ~> G) := whiskerr_is_nat H eta. -End nat_map_right. +Definition whiskerr (H : C ~> D) (eta : F ~> G) : (H \; F) ~> (H \; G) := + whiskerr_fun H eta : Natural.type _ _. +End right_whiskering. -Notation "F <$o> n" := (nat_rmap F n) +Notation "F <$o> n" := (whiskerr F n) (at level 58, format "F <$o> n", right associativity) : cat_scope. +Definition whisker {C : cat} {D : precat} {E : cat} + {F G : C ~>_precat D} {H K : D ~> E} + (eta : F ~> G) (mu : H ~> K) : (F \; H) ~> (G \; K) := + (eta H) \; (G <$o> mu). + +Notation "eta mu" := (whisker eta mu) + (at level 58, format "eta mu", right associativity) : cat_scope. + +Lemma whiskern1 {C D E : cat} {F G : C ~>_precat D} (eta : F ~> G) (H : D ~> E) : + eta \idmap_H = eta H. +Proof. by apply/natP/funext=> c /=; apply: compo1. Qed. + +Lemma whisker1n {C D E : cat} {F G : D ~> E} (H : C ~> D) (eta : F ~> G) : + \idmap_H eta = H <$o> eta. +Proof. +apply/natP/funext=> c /=; rewrite /natural_comp/=. +by rewrite [X in X \; _]F1 comp1o. +Qed. + Definition delta (C D : cat) : C -> (D ~> C) := cst D. Arguments delta C D : clear implicits. @@ -599,13 +630,6 @@ HB.builders Context C M of IsJoinCoMonad C M. (fun a b f => erefl) unit_cojoin join_counit cojoin_square. HB.end. -Lemma idFmap (C : cat) (a b : C) (f : a ~> b) : idfun <$> f = f. -Proof. by []. Qed. - -Lemma compFmap (C D E : cat) (F : C ~> D) (G : D ~> E) (a b : C) (f : a ~> b) : - (G \o F) <$> f = G <$> F <$> f. -Proof. by []. Qed. - (* yoneda *) Section hom_repr. Context {C : cat} (F : C ~>_cat U). @@ -737,70 +761,125 @@ Notation "F `/ b" := (F `/` cst unit b) (at level 40, b at level 40, format "F `/ b") : cat_scope. Notation "a / b" := (cst unit a `/ b) : cat_scope. -(* (* Not working yet *) *) -(* HB.mixin Record IsInitial {C : quiver} (i : C) := { *) -(* to : forall c, i ~> c; *) -(* to_unique : forall c (f : i ~> c), f = to c *) -(* }. *) -(* #[short(type="initial")] *) -(* HB.structure Definition Initial {C : quiver} := {i of IsInitial C i}. *) - -(* HB.mixin Record IsTerminal {C : quiver} (t : C) := { *) -(* from : forall c, c ~> t; *) -(* from_unique : forall c (f : c ~> t), f = from c *) -(* }. *) -(* #[short(type="terminal")] *) -(* HB.structure Definition Terminal {C : quiver} := {t of IsTerminal C t}. *) -(* #[short(type="universal")] *) -(* HB.structure Definition Universal {C : quiver} := *) -(* {u of Initial C u & Terminal C u}. *) - -(* Definition hom' {C : precat} (a b : C) := a ~> b. *) -(* (* Bug *) *) -(* Identity Coercion hom'_hom : hom' >-> hom. *) - -(* HB.mixin Record IsMono {C : precat} (b c : C) (f : hom b c) := { *) -(* monoP : forall (a : C) (g1 g2 : a ~> b), g1 \; f = g2 \; f -> g1 = g2 *) -(* }. *) -(* #[short(type="mono")] *) -(* HB.structure Definition Mono {C : precat} (a b : C) := {m of IsMono C a b m}. *) -(* Notation "a >~> b" := (mono a b) *) -(* (at level 99, b at level 200, format "a >~> b") : cat_scope. *) -(* Notation "C >~>_ T D" := (@mono T C D) *) -(* (at level 99, T at level 0, only parsing) : cat_scope. *) - -(* HB.mixin Record IsEpi {C : precat} (a b : C) (f : hom a b) := { *) -(* epiP : forall (c : C) (g1 g2 : b ~> c), g1 \o f = g2 \o f -> g1 = g2 *) -(* }. *) -(* #[short(type="epi")] *) -(* HB.structure Definition Epi {C : precat} (a b : C) := {e of IsEpi C a b e}. *) -(* Notation "a ~>> b" := (epi a b) *) -(* (at level 99, b at level 200, format "a ~>> b") : cat_scope. *) -(* Notation "C ~>>_ T D" := (@epi T C D) *) -(* (at level 99, T at level 0, only parsing) : cat_scope. *) - -(* #[short(type="iso")] *) -(* HB.structure Definition Iso {C : precat} (a b : C) := *) -(* {i of @Mono C a b i & @Epi C a b i}. *) -(* Notation "a <~> b" := (epi a b) *) -(* (at level 99, b at level 200, format "a <~> b") : cat_scope. *) -(* Notation "C <~>_ T D" := (@epi T C D) *) -(* (at level 99, T at level 0, only parsing) : cat_scope. *) - -HB.mixin Record IsRightAdjoint (D C : precat) (R : D -> C) - of @PreFunctor D C R := { - L_ : C ~> D; - phi : forall c d, (L_ c ~> d) -> (c ~> R d); - psy : forall c d, (c ~> R d) -> (L_ c ~> d); - phi_psy c d : (phi c d \o psy c d)%FUN = @id (c ~> R d); - psy_phi c d : (psy c d \o phi c d)%FUN = @id (L_ c ~> d) +Definition obj (C : quiver) : Type := C. +HB.mixin Record IsInitial {C : quiver} (i : obj C) := { + to : forall c, i ~> c; + to_unique : forall c (f : i ~> c), f = to c +}. +#[short(type="initial")] +HB.structure Definition Initial {C : quiver} := {i of IsInitial C i}. + +HB.mixin Record IsTerminal {C : quiver} (t : obj C) := { + from : forall c, c ~> t; + from_unique : forall c (f : c ~> t), f = from c +}. +#[short(type="terminal")] +HB.structure Definition Terminal {C : quiver} := {t of IsTerminal C t}. + +HB.mixin Record IsMono {C : precat} (b c : C) (f : hom b c) := { + monoP : forall (a : C) (g1 g2 : a ~> b), g1 \; f = g2 \; f -> g1 = g2 +}. +#[short(type="mono")] +HB.structure Definition Mono {C : precat} (a b : C) := {m of IsMono C a b m}. +Notation "a >~> b" := (mono a b) + (at level 99, b at level 200, format "a >~> b") : cat_scope. +Notation "C >~>_ T D" := (@mono T C D) + (at level 99, T at level 0, only parsing) : cat_scope. + +HB.mixin Record IsEpi {C : precat} (a b : C) (f : hom a b) := { + epiP : forall (c : C) (g1 g2 : b ~> c), g1 \o f = g2 \o f -> g1 = g2 +}. +#[short(type="epi")] +HB.structure Definition Epi {C : precat} (a b : C) := {e of IsEpi C a b e}. +Notation "a ~>> b" := (epi a b) + (at level 99, b at level 200, format "a ~>> b") : cat_scope. +Notation "C ~>>_ T D" := (@epi T C D) + (at level 99, T at level 0, only parsing) : cat_scope. + +#[short(type="iso")] +HB.structure Definition Iso {C : precat} (a b : C) := + {i of @Mono C a b i & @Epi C a b i}. +Notation "a <~> b" := (epi a b) + (at level 99, b at level 200, format "a <~> b") : cat_scope. +Notation "C <~>_ T D" := (@epi T C D) + (at level 99, T at level 0, only parsing) : cat_scope. + +Definition comp1F {C D : cat} (F : C ~> D) : idmap \; F = F. +Proof. by apply/functorP=> a b f; rewrite funext_frefl/= compFmap. Qed. + +Definition compF1 {C D : cat} (F : C ~> D) : F \; idmap = F. +Proof. by apply/functorP=> a b f; rewrite funext_frefl/= compFmap. Qed. + +Definition feq {C : precat} {a b : C} : a = b -> a ~> b. +Proof. by move<-; exact idmap. Defined. + +Definition feqsym {C : precat} {a b : C} : a = b -> b ~> a. +Proof. by move<-; exact idmap. Defined. + +HB.mixin Record IsLeftAdjointOf (C D : cat) (R : D ~> C) L + of @Functor C D L := { + Lphi : forall c d, (L c ~> d) -> (c ~> R d); + Lpsi : forall c d, (c ~> R d) -> (L c ~> d); + (* there should be a monad and comonad structure wrappers instead *) + Lunit : (idmap : C ~> C) ~~> R \o ((L : Functor.type C D) : C ~> D); + Lcounit : ((L : Functor.type C D) : C ~> D) \o R ~~> idmap :> D ~> D; + LphiE : forall c d (g : L c ~> d), Lphi c d g = Lunit c \; (R <$> g); + LpsiE : forall c d (f : c ~> R d), Lpsi c d f = (L <$> f) \; Lcounit d; + Lwhiskerlr : let L : C ~> D := L : Functor.type C D in + (feqsym (comp1F _) \; Lunit L) \; + (L <$o> Lcounit \; feq (compF1 _)) = idmap; + Lwhiskerrl : let L : C ~> D := L : Functor.type C D in + (feqsym (compF1 _) \; R <$o> Lunit) \; + (Lcounit R \; feq (comp1F _)) = idmap; +}. +#[short(type="left_adjoint_of")] +HB.structure Definition LeftAdjointOf (C D : cat) (R : D ~> C) := + { L of @Functor C D L & IsLeftAdjointOf C D R L}. +Arguments Lphi {C D R s} {c d}. +Arguments Lpsi {C D R s} {c d}. +Arguments Lunit {C D R s}. +Arguments Lcounit {C D R s}. + +Section LeftAdjointOf_Theory. +Variables (C D : cat) (R : D ~> C) (L : LeftAdjointOf.type R). + +Lemma Lphi_psi (c : C) (d : D) : + (@Lphi _ _ R L c d \o @Lpsi _ _ R L c d)%FUN = @id (c ~> R d). +Proof. +apply/funext => f /=; rewrite LphiE LpsiE. +Admitted. + +Lemma Lpsi_phi (c : C) (d : D) : + (@Lpsi _ _ R L c d \o @Lphi _ _ R L c d)%FUN = @id (L c ~> d). +Proof. +Admitted. +End LeftAdjointOf_Theory. + +HB.mixin Record IsRightAdjoint (D C : cat) (R : D -> C) + of @Functor D C R := { + (* we should have a wrapper instead *) + left_adjoint : C ~> D; + LLphi : forall c d, (left_adjoint c ~> d) -> (c ~> R d); + LLpsi : forall c d, (c ~> R d) -> (left_adjoint c ~> d); + LLunit : (idmap : C ~> C) ~~> (R : Functor.type D C) \o left_adjoint; + LLcounit : left_adjoint \o (R : Functor.type D C) ~~> idmap :> D ~> D; + LLphiE : forall c d (g : left_adjoint c ~> d), LLphi c d g = LLunit c \; (R <$> g); + LLpsiE : forall c d (f : c ~> R d), LLpsi c d f = (left_adjoint <$> f) \; LLcounit d; + LLwhiskerlr : + (feqsym (comp1F _) \; LLunit left_adjoint) \; + (left_adjoint <$o> LLcounit \; feq (compF1 _)) = idmap; + LLwhiskerrl : + (feqsym (compF1 _) \; (R : Functor.type D C) <$o> LLunit) \; + (LLcounit (R : Functor.type D C) \; feq (comp1F _)) = idmap; }. #[short(type="right_adjoint")] -HB.structure Definition RightAdjoint (D C : precat) := +HB.structure Definition RightAdjoint (D C : cat) := { R of @Functor D C R & IsRightAdjoint D C R }. -Arguments L_ {_ _}. -Arguments phi {D C s} {c d}. -Arguments psy {D C s} {c d}. +Arguments left_adjoint {_ _}. +Arguments LLphi {D C s} {c d}. +Arguments LLpsi {D C s} {c d}. +Arguments LLunit {D C s}. +Arguments LLcounit {D C s}. HB.mixin Record PreCat_IsMonoidal C of PreCat C := { onec : C; @@ -817,7 +896,8 @@ Notation "f <*> g" := (prod^$ ((f, g) : (_, _) ~> (_, _))) (only parsing) : cat_scope. Notation "1" := onec : cat_scope. -Definition hom_cast {C : quiver} {a a' : C} (eqa : a = a') {b b' : C} (eqb : b = b') : +Definition hom_cast {C : quiver} {a a' : C} (eqa : a = a') + {b b' : C} (eqb : b = b') : (a ~> b) -> (a' ~> b'). Proof. now elim: _ / eqa; elim: _ / eqb. Defined. @@ -881,113 +961,326 @@ HB.structure Definition Monoidal : Set := { C of PreMonoidal_IsMonoidal C & PreMonoidal C }. Set Universe Checking. -HB.mixin Record IsRing A := { - zero : A; - one : A; - add : A -> A -> A; - opp : A -> A; - mul : A -> A -> A; - addrA : associative add; - addrC : commutative add; - add0r : left_id zero add; - addNr : left_inverse zero opp add; - mulrA : associative mul; - mul1r : left_id one mul; - mulr1 : right_id one mul; - mulrDl : left_distributive mul add; - mulrDr : right_distributive mul add; +Record span (Q : quiver) (A B : Q) := Span { + bot : Q; + bot2left : bot ~> A; + bot2right : bot ~> B }. -#[short(type="ring")] -HB.structure Definition Ring := { A of IsRing A }. +Section spans. +Variables (Q : precat) (A B : Q). +Record span_map (c c' : span A B) := SpanMap { + bot_map : bot c ~> bot c'; + bot2left_map : bot_map \; bot2left c' = bot2left c; + bot2right_map : bot_map \; bot2right c' = bot2right c; +}. +HB.instance Definition _ := IsQuiver.Build (span A B) span_map. -Bind Scope algebra_scope with Ring.sort. -Notation "0" := zero : algebra_scope. -Notation "1" := one : algebra_scope. -Infix "+" := (@add _) : algebra_scope. -Notation "- x" := (@opp _ x) : algebra_scope. -Infix "*" := (@mul _) : algebra_scope. -Notation "x - y" := (x + - y) : algebra_scope. +Lemma span_mapP (c c' : span A B) (f g : c ~> c') : + bot_map f = bot_map g <-> f = g. +Proof. +split=> [|->]//; case: f g => [/= f ? ?] [/= g + +] efg. +by elim: efg => // ? ?; congr SpanMap; apply: Prop_irrelevance. +Qed. -Lemma addr0 (R : ring) : right_id (@zero R) add. -Proof. by move=> x; rewrite addrC add0r. Qed. +End spans. + +Section spans_in_cat. +Variables (Q : cat) (A B : Q). +Definition span_idmap (c : span A B) := + @SpanMap Q A B c c idmap (comp1o _) (comp1o _). +Program Definition span_comp (c1 c2 c3 : span A B) + (f12 : c1 ~> c2) (f23 : c2 ~> c3) := + @SpanMap Q A B c1 c3 (bot_map f12 \; bot_map f23) _ _. +Next Obligation. by rewrite -compoA !bot2left_map. Qed. +Next Obligation. by rewrite -compoA !bot2right_map. Qed. +HB.instance Definition _ := IsPreCat.Build (span A B) + span_idmap span_comp. + +Lemma span_are_cats : PreCat_IsCat (span A B). +Proof. +constructor=> [a b f|a b f|a b c d f g h]. +- by apply/span_mapP => /=; rewrite comp1o. +- by apply/span_mapP => /=; rewrite compo1. +- by apply/span_mapP => /=; rewrite compoA. +Qed. +HB.instance Definition _ := span_are_cats. +End spans_in_cat. -Lemma addrN (R : ring) : right_inverse (@zero R) opp add. -Proof. by move=> x; rewrite addrC addNr. Qed. +Record cospan (Q : quiver) (A B : Q) := Cospan { + top : Q; + left2top : A ~> top; + right2top : B ~> top +}. -Lemma addKr (R : ring) (x : R) : cancel (add x) (add (- x)). -Proof. by move=> y; rewrite addrA addNr add0r. Qed. +Section cospans. +Variables (Q : precat) (A B : Q). +Record cospan_map (c c' : cospan A B) := CospanMap { + top_map : top c ~> top c'; + left2top_map : left2top c \; top_map = left2top c'; + right2top_map : right2top c \; top_map = right2top c'; +}. +HB.instance Definition _ := IsQuiver.Build (cospan A B) cospan_map. -Lemma addrI (R : ring) (x : R) : injective (add x). -Proof. exact: can_inj (addKr _). Qed. +Lemma cospan_mapP (c c' : cospan A B) (f g : c ~> c') : + top_map f = top_map g <-> f = g. +Proof. +split=> [|->]//; case: f g => [/= f ? ?] [/= g + +] efg. +by elim: efg => // ? ?; congr CospanMap; apply: Prop_irrelevance. +Qed. -Lemma opprK (R : ring) : involutive (@opp R). -Proof. by move=> x; apply: (@addrI _ (- x)); rewrite addNr addrN. Qed. +End cospans. + +Section cospans_in_cat. +Variables (Q : cat) (A B : Q). +Definition cospan_idmap (c : cospan A B) := + @CospanMap Q A B c c idmap (compo1 _) (compo1 _). +Program Definition cospan_comp (c1 c2 c3 : cospan A B) + (f12 : c1 ~> c2) (f23 : c2 ~> c3) := + @CospanMap Q A B c1 c3 (top_map f12 \; top_map f23) _ _. +Next Obligation. by rewrite compoA !left2top_map. Qed. +Next Obligation. by rewrite compoA !right2top_map. Qed. +HB.instance Definition _ := IsPreCat.Build (cospan A B) + cospan_idmap cospan_comp. + +Lemma cospan_are_cats : PreCat_IsCat (cospan A B). +Proof. +constructor=> [a b f|a b f|a b c d f g h]. +- by apply/cospan_mapP => /=; rewrite comp1o. +- by apply/cospan_mapP => /=; rewrite compo1. +- by apply/cospan_mapP => /=; rewrite compoA. +Qed. +HB.instance Definition _ := cospan_are_cats. +End cospans_in_cat. -HB.mixin Record IsRingHom (A B : ring) (f : A -> B) := { - hom1_subproof : f 1%A = 1%A; - homB_subproof : {morph f : x y / x - y}; - homM_subproof : {morph f : x y / (x * y)%A}; +HB.mixin Record isPrePullback (Q : precat) (A B : Q) + (c : cospan A B) (s : span A B) := { + is_square : bot2left s \; left2top c = bot2right s \; right2top c; }. +#[short(type=prepullback)] +HB.structure Definition PrePullback Q A B (c : cospan A B) := + {s of isPrePullback Q A B c s}. +Arguments prepullback {Q A B} c. -HB.structure Definition RingHom A B := { f of IsRingHom A B f }. +Section prepullback. +Variables (Q : precat) (A B : Q) (c : cospan A B). +HB.instance Definition _ := + IsQuiver.Build (prepullback c) + (fun a b => (a : span A B) ~>_(span A B) (b : span A B)). +Lemma eq_prepullbackP (p q : prepullback c) : + p = q :> span _ _ <-> p = q. +Proof. +Admitted. +End prepullback. +Section prepullback. +Variables (Q : cat) (A B : Q) (csp : cospan A B). +(* TODO: why can't we do that? *) +(* HB.instance Definition _ := Cat.on (prepullback csp). *) +HB.instance Definition _ := + Quiver_IsPreCat.Build (prepullback csp) + (fun a => \idmap_(a : span A B)) + (* TODO: study how to make this coercion trigger + even when the target is not reduced to span *) + (fun a b c f g => f \; g). +Lemma prepullback_is_cat : PreCat_IsCat (prepullback csp). +Proof. (* should be copied from the cat on span *) +constructor=> [a b f|a b f|a b c d f g h]; + [exact: comp1o|exact: compo1|exact: compoA]. +Qed. +End prepullback. + +HB.tag Definition pb_terminal (Q : precat) + (A B : Q) (c : cospan A B) (s : prepullback c) : + obj (prepullback c) := s. + +#[wrapper] +HB.mixin Record prepullback_isTerminal (Q : precat) + (A B : Q) (c : cospan A B) + (s : span A B) of isPrePullback Q A B c s := { + prepullback_terminal : + IsTerminal (prepullback c) (pb_terminal s) +}. +#[short(type="pullback"), verbose] +HB.structure Definition Pullback (Q : precat) + (A B : Q) (c : cospan A B) := + {s of isPrePullback Q A B c s + & IsTerminal (prepullback c) (pb_terminal s) }. + +Inductive walking_cospan := Top | Left | Right. +Definition walking_cospan_hom (x y : walking_cospan) := match x, y with + | Top, Top | Left, Left | Right, Right | + Left, Top | Right, Top => Datatypes.unit + | _, _ => False + end. -Lemma id_IsRingHom A : IsRingHom A A idfun. Proof. by []. Defined. -HB.instance Definition _ A := id_IsRingHom A. +HB.instance Definition _ := + IsQuiver.Build walking_cospan walking_cospan_hom. + +Definition walking_cospan_id (x : walking_cospan) : x ~> x. +Proof. by case: x; constructor. Defined. + +Definition walking_cospan_comp (x y z : walking_cospan) : + (x ~> y) -> (y ~> z) -> (x ~> z). +Proof. by case: x y z => [] [] []. Defined. + +HB.instance Definition _ := Quiver_IsPreCat.Build walking_cospan + walking_cospan_id walking_cospan_comp. + +Lemma walking_cospan_cat : PreCat_IsCat walking_cospan. +Proof. by constructor=> [[] []|[] []|[] [] [] []]// []. Qed. +HB.instance Definition _ := walking_cospan_cat. + +Section Pullback_Natural. +Context (C : cat) (A B : C) (csp : cospan A B). + +Definition cspF (x : walking_cospan) : C := + match x with Left => A | Right => B | Top => top csp end. -Lemma comp_IsRingHom (A B C : ring) - (f : RingHom.type A B) (g : RingHom.type B C) : - IsRingHom A C (f \; g :> U). +Definition cspFhom : forall (x y : walking_cospan), + (x ~> y) -> cspF x ~> cspF y. Proof. -by constructor => [|x y|x y]; -rewrite /comp/= ?hom1_subproof ?homB_subproof ?homM_subproof. +move=> [] []//. +- move=> _; exact: idmap. +- move=> _; exact: left2top csp. +- move=> _; exact: idmap. +- move=> _; exact: right2top csp. +- move=> _; exact: idmap. +Defined. + +HB.instance Definition _ := IsPreFunctor.Build _ _ cspF cspFhom. +Lemma cspF_functor : PreFunctor_IsFunctor _ _ cspF. +Proof. +by constructor=> [[]|[] [] []]//= [] []//=; + rewrite ?(compo1, comp1o)//. Qed. -HB.instance Definition _ A B C f g := @comp_IsRingHom A B C f g. +HB.instance Definition _ := cspF_functor. -HB.instance Definition _ := IsQuiver.Build ring RingHom.type. -HB.instance Definition _ := - Quiver_IsPreCat.Build ring (fun _ => idfun) (fun _ _ _ f g => f \; g :> U). -HB.instance Definition _ := Quiver_IsPreConcrete.Build ring (fun _ _ => id). -Lemma ring_precat : PreConcrete_IsConcrete ring. -Proof. -constructor => A B [f cf] [g cg]//=; rewrite -[_ = _]/(f = g) => fg. -case: _ / fg in cg *; congr {|RingHom.sort := _ ; RingHom.class := _|}. -case: cf cg => [[? ? ?]] [[? ? ?]]. -by congr RingHom.Class; congr IsRingHom.phant_Build => //=; apply: Prop_irrelevance. +Section prepullback2natural. +Variable (p : prepullback csp). + +Definition wcsp w : cst walking_cospan (bot p) w ~> cspF w. +Proof. +case: w; rewrite /cst /=. +- exact: (bot2left _ \; left2top _). +- exact: bot2left. +- exact: bot2right. +Defined. + +Lemma wcsp_natural : IsNatural _ _ _ _ wcsp. +Proof. +constructor=> - [] [] //= [] /=; rewrite ?(comp1o, compo1)//=. +exact: is_square. Qed. -HB.instance Definition _ := ring_precat. -Lemma ring_IsCat : PreCat_IsCat ring. +End prepullback2natural. + +Section natural2prepullback. +Variables (c : C) (n : cst walking_cospan c ~~> cspF). + +Definition s := {| bot := c; bot2left := n Left; bot2right := n Right |}. + +Lemma s_prepullback : isPrePullback _ _ _ csp s. Proof. -by constructor=> [A B f|A B f|A B C D f g h]; exact: concrete_fun_inj. +constructor => /=. +have p := natural n (tt : Right ~> Top). +have /esym q := natural n (tt : Left ~> Top). +exact: etrans q p. Qed. -HB.instance Definition _ := ring_IsCat. - -Lemma hom1 (R S : ring) (f : R ~> S) : f 1%A = 1%A. -Proof. exact: hom1_subproof. Qed. -Lemma homB (R S : ring) (f : R ~> S) : {morph f : x y / x - y}. -Proof. exact: homB_subproof. Qed. -Lemma homM (R S : ring) (f : R ~> S) : {morph f : x y / (x * y)%A}. -Proof. exact: homM_subproof. Qed. -Lemma hom0 (R S : ring) (f : R ~> S) : f 0%A = 0%A. -Proof. by rewrite -(addrN 1%A) homB addrN. Qed. -Lemma homN (R S : ring) (f : R ~> S) : {morph f : x / - x}. -Proof. by move=> x; rewrite -[- x]add0r homB hom0 add0r. Qed. -Lemma homD (R S : ring) (f : R ~> S) : {morph f : x y / x + y}. -Proof. by move=> x y; rewrite -[y]opprK !homB !homN. Qed. - -HB.mixin Record IsIdeal (R : ring) (I : R -> Prop) := { - ideal0 : I 0; - idealD : forall x y, I x -> I y -> I (x + y); - idealM : forall x y, I y -> I (x * y)%A; -}. -HB.structure Definition Ideal (R : ring) := { I of IsIdeal R I }. -HB.mixin Record Ideal_IsPrime (R : ring) (I : R -> Prop) of IsIdeal R I := { - ideal_prime : forall x y : R, I (x * y)%A -> I x \/ I y -}. -#[short(type="spectrum")] -HB.structure Definition PrimeIdeal (R : ring) := - { I of Ideal_IsPrime R I & Ideal R I }. +End natural2prepullback. + +End Pullback_Natural. + +Notation square u v f g := + (isPrePullback _ _ _ (Cospan f g) (Span u v)). +Notation pbsquare u v f g := + (Pullback _ (Cospan f g) (Span u v)). +Notation pb s := (prepullback_isTerminal _ _ _ _ s). + +Notation "P <=> Q" := ((P -> Q) * (Q -> P))%type (at level 70). + +Notation "'sigma' x .. y , p" := + (sigT (fun x => .. (sigT (fun y => p)) ..)) + (at level 200, x binder, right associativity, + format "'[' 'sigma' '/ ' x .. y , '/ ' p ']'") + : cat_scope. + +(**********************************************************************) + +Section th_of_pb. +Variables (Q : cat) (A B C D E F : Q). +Variables (f : A ~> D) (g : B ~> D) (h : C ~> A). +Variables (u : E ~> A) (v : E ~> B) (w : F ~> C) (z : F ~> E). +Variable (uvfg : pbsquare u v f g). + +Theorem pbsquarec_compP : + pbsquare w z h u <=> pbsquare w (z \; v) (h \; f) g. +Proof. +split=> [] sq. + + have @sq_ispb : pullback (Cospan h u) := HB.pack (Span w z) sq. + have @uvfg_ispb : pullback (Cospan f g) := HB.pack (Span u v) uvfg. + have /=E2 := @is_square _ _ _ _ sq_ispb. + have /=E1 := @is_square _ _ _ _ uvfg_ispb. + + have p1 : @isPrePullback Q C B (Cospan (h \; f) g) (Span w (z \; v)). + by constructor; rewrite /= compoA E2 -compoA E1 compoA. + pose big_black_square : prepullback (Cospan (h \; f) g) := + HB.pack (Span w (z \; v)) p1. + + have @from : forall + (big_red_square : prepullback {| top := D; left2top := h \; f; right2top := g |}), + big_red_square ~> pb_terminal big_black_square. + + move=> big_red_square; unfold pb_terminal. + + have /= := @is_square _ _ _ _ big_red_square. + + pose F' := bot big_red_square. + set w' : F' ~> C := bot2left big_red_square. + set z' : F' ~> B := bot2right big_red_square. + move=> E3. + + have xxx : isPrePullback Q A B (Cospan f g) (Span (w' \; h) z'). + by constructor=> /=; rewrite -compoA E3. + pose red_black_square : prepullback (Cospan f g) := + HB.pack (Span (w' \; h) z') xxx. + have := @from_unique _ (pb_terminal uvfg_ispb) red_black_square. + set blue := @from _ (pb_terminal uvfg_ispb) red_black_square. + move=> blue_unique. + + have p3 : @isPrePullback Q C E (Cospan h u) (Span w' (bot_map blue)). + by constructor; rewrite /= (bot2left_map blue). (* buggy unifier without blue *) + pose blue_red_black_square : prepullback (Cospan h u) := + HB.pack (Span w' (bot_map blue)) p3. + + pose red := @from _ (pb_terminal sq_ispb) blue_red_black_square. + + admit. + + + + have p2 : prepullback_isTerminal.axioms_ Q C B (Cospan (h \; f) g) (Span w (z \; v)) p1. + constructor. econstructor=> /=. + admit. + + by HB.from p1 p2. + +Admitted. + +End th_of_pb. + + +Module test. + +Section test. +Variables (Q : precat) (A B : Q) (c : cospan A B). +Variable (p : pullback c). +Check pb_terminal p : terminal _. + +End test. +End test. + + diff --git a/theories/encat.v b/theories/encat.v new file mode 100644 index 000000000..d8394cfbe --- /dev/null +++ b/theories/encat.v @@ -0,0 +1,512 @@ +Require Import ssreflect ssrfun. +Unset Universe Checking. +From HB Require Import structures cat. +Set Universe Checking. +Require Import Coq.Program.Equality. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. +Add Search Blacklist "__canonical__". + +Local Open Scope algebra_scope. + +Local Open Scope cat_scope. + +(* +Notation "'sigma' x .. y , p" := + (sigT (fun x => .. (sigT (fun y => p)) ..)) + (at level 200, x binder, right associativity, + format "'[' 'sigma' '/ ' x .. y , '/ ' p ']'") + : type_scope. +*) + +(*** DOUBLE CATEGORIES (REVISED) *) + +(* transpose for horizontal morphism quiver. + HB.tag needed to identify transpose as lifter *) +HB.tag Definition transpose (C : quiver) : U := C. +#[wrapper] HB.mixin Record IsTQuiver C of IsQuiver C := { + is_tquiver : IsQuiver (transpose C) +}. +(* vertical and horizontal quivers, defining cells *) +Unset Universe Checking. +#[short(type="cquiver")] +HB.structure Definition CQuiver : Set := { C of IsQuiver C & IsTQuiver C }. +Set Universe Checking. + +HB.tag Definition hhom (c : CQuiver.type) : c -> c -> U := @hom (transpose c). + +(* record to represent the set of morphims + (needed for 2-objects, i.e. horizontal morphisms) *) +Record Total2 T (h: T -> T -> U) : Type := HO { + source : T; + target : T; + this_morph : h source target }. + +(* the set of horizontal morphisms. *) +HB.tag Definition HHomSet (C: cquiver) := Total2 (@hhom C). + +(* source functor (for horizontal morphisms): D1 -> D0. + defined as object-level function, by functoriality lifted to a + (2-cell, vertical) morphism-level one *) +HB.tag Definition HSource C := fun (X: HHomSet C) => @source C (@hhom C) X. +(* target functor (for horizontal morphisms): D1 -> D0. *) +HB.tag Definition HTarget C := fun (X: HHomSet C) => @target C (@hhom C) X. + +(* D1 quiver requirement. *) +#[wrapper] +HB.mixin Record IsDQuiver T of CQuiver T := { is_dquiver : Quiver (HHomSet T) }. +Unset Universe Checking. +#[short(type="dquiver")] +HB.structure Definition DQuiver : Set := { C of IsDQuiver C }. +Set Universe Checking. + +(* used to define composable pairs of morphisms as a set *) +Record GenComp T (h: T -> T -> U) := GC { + h_one : T; + h_two : T ; + h_three : T; + h_first : h h_one h_two ; + h_second : h h_two h_three +}. + +(* composable pairs of horizontal morphisms as a set *) +HB.tag Definition HCompSet (C: cquiver) := GenComp (@hhom C). + +Definition H2First (C: cquiver) (X: @HCompSet C) : HHomSet C := + @HO C _ (h_one X) (h_two X) (h_first X). +Definition H2Second (C: cquiver) (X: @HCompSet C) : HHomSet C := + @HO C _ (h_two X) (h_three X) (h_second X). + +(* hunit - horizontal unit functor. + + hcomp - horizontal composition functor. + + Both specified as object-level functions, to be lifted by + functoriality to morphism-level ones. + + At the object level, hunit gives a horizontal identity morphism + for each D0 object. At the morphism level, it gives horizontal + 2-cell identity for each vertical morphism. + + In the case of hcomp, relying on functoriality requires some care + in defining the pullback category, making sure that adjacency at + the object-level (between horizontal morphisms) is matched by + adjacency at the morphism-level (between 2-cells). *) +HB.mixin Record IsHDQuiver T of DQuiver T := { + hunit : forall a: T, @hhom T a a ; + hcomp : forall (a b c: T), @hhom T a b -> @hhom T b c -> @hhom T a c; +}. +Unset Universe Checking. +#[short(type="hdquiver")] +HB.structure Definition HDQuiver : Set := { C of IsHDQuiver C }. +Set Universe Checking. + +Definition hhunit (T: hdquiver) (a: T) : HHomSet T := + @HO T (@hhom T) a a (hunit a). + +(* horizontal composition of two horizontal morphisms from a + cell product *) +Definition hhcomp (T: hdquiver) (x: HCompSet T) : HHomSet T := + match x with + @GC _ _ a b c h1 h2 => @HO T (@hhom T) a c (hcomp a b c h1 h2) end. + +(* Precategory based on the DQuiver (i.e. precategory D1). Gives: + vertical 2-cell identity morphism. + vertical 2-cell composition. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsC2PreCat T of DQuiver T := { + is_c2precat : Quiver_IsPreCat (@HHomSet T) }. +#[short(type="c2precat")] +HB.structure Definition C2PreCat : Set := { C of IsC2PreCat C }. +Set Universe Checking. + +(* The category based on the DQuiver (i.e. category D1). *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsC2Cat T of C2PreCat T := { + is_c2cat : PreCat_IsCat (@HHomSet T) }. +#[short(type="c2cat")] +HB.structure Definition C2Cat : Set := { C of IsC2Cat C }. +Set Universe Checking. + +(* horizontal unit functor: D0 -> D1 *) +HB.tag Definition HUnit (C: hdquiver) := + fun (x: HDQuiver.sort C) => @hhunit C x. +(* horizontal composition functor: D1 * D1 -> D1 *) +HB.tag Definition HComp (C: hdquiver) := + fun (x: HCompSet C) => @hhcomp C x. + +(* source prefunctor. + HHomSet T is the quiver of the 2-morphisms, thanks to DQuiver. + T is the quiver of 1-morphisms. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsSPreFunctor T of Cat T & C2Cat T := { + is_sprefunctor : IsPreFunctor (HHomSet T) T (@HSource T) }. +HB.structure Definition SPreFunctor : Set := {C of IsSPreFunctor C}. +Set Universe Checking. + +(* target prefunctor. *) +Unset Universe Checking. +#[wrapper] + HB.mixin Record IsTPreFunctor T of SPreFunctor T := { + is_tprefunctor : IsPreFunctor (HHomSet T) T (@HTarget T) }. +HB.structure Definition TPreFunctor : Set := {C of IsTPreFunctor C}. +Set Universe Checking. + +(* source functor. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record SPreFunctor_IsFunctor T of TPreFunctor T := { + is_sfunctor : PreFunctor_IsFunctor (HHomSet T) T (@HSource T) }. +HB.structure Definition SFunctor : Set := {C of SPreFunctor_IsFunctor C}. +Set Universe Checking. + +(* target functor. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record TPreFunctor_IsFunctor T of SFunctor T := { + is_tfunctor : PreFunctor_IsFunctor (HHomSet T) T (@HTarget T) }. +HB.structure Definition TFunctor : Set := {C of TPreFunctor_IsFunctor C}. +Set Universe Checking. + +(* unit prefunctor. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsUPreFunctor T of HDQuiver T & TFunctor T := + { is_uprefunctor : IsPreFunctor T (HHomSet T) (@HUnit T) }. +HB.structure Definition UPreFunctor : Set := {C of IsUPreFunctor C}. +Set Universe Checking. + +(* unit functor. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record UPreFunctor_IsFunctor T of UPreFunctor T := { + is_ufunctor : PreFunctor_IsFunctor T (HHomSet T) (@HUnit T) }. +HB.structure Definition UFunctor : Set := {C of UPreFunctor_IsFunctor C}. +Set Universe Checking. + +(* 2-cell (D1) morphisms *) +Definition c2hom (D: HDQuiver.type) : HHomSet D -> HHomSet D -> U := + @hom (HHomSet D). + +Definition C2Hom (D: HDQuiver.type) (a b c d: D) (h0: hhom a b) + (h1: hhom c d) : U := c2hom (HO h0) (HO h1). + +(* The set of D1 morphisms *) +HB.tag Definition C2HomSet (C: HDQuiver.type) := Total2 (@c2hom C). + +(* horizontal 2-cell unit (maps vertical morphisms to horizontally + unitary 2-cells) *) +Definition HC2Unit (T: UFunctor.type) (a b: T) (m: @hom T a b) : + c2hom (HUnit a) (HUnit b) := @Fhom _ _ (@HUnit T) a b m. + +(* 2-cell source *) +Definition HC2Source (T: UFunctor.type) (a b: @HHomSet T) + (m: @c2hom T a b) : + @hom T (HSource a) (HSource b) := @Fhom _ _ (@HSource T) a b m. + +(* 2-cell target *) +Definition HC2Target (T: UFunctor.type) (a b: @HHomSet T) + (m: @c2hom T a b) : + @hom T (HTarget a) (HTarget b) := @Fhom _ _ (@HTarget T) a b m. + +(* horizontal composition of two (naked) horizontal morphisms *) +Definition l_hcomp (T: UFunctor.type) (a0 a1 a2: T) + (h0: hhom a0 a1) (h1: hhom a1 a2) : HHomSet T := + @HO T _ a0 a2 (hcomp a0 a1 a2 h0 h1). + + +(** HCompSet T is the pseudo-pullback category used to deal with + products of D1 (where the adjacency condition is expressed + w.r.t. D0 *) + +Notation "'sigma' x .. y , p" := (sigT (fun x => .. (sigT (fun y => p)) ..)) + (at level 200, x binder, right associativity, + format "'[' 'sigma' '/ ' x .. y , '/ ' p ']'") + : type_scope. + +(** HCompSet quiver *) +Definition HComp_hom (T: UFunctor.type) (x y: HCompSet T) := + sigma (hh0: C2Hom (h_first x) (h_first y)) + (hh1: C2Hom (h_second x) (h_second y)), + HC2Target hh0 = HC2Source hh1. + +HB.instance Definition HCompQuiver (T: UFunctor.type) : + IsQuiver (HCompSet T) := + IsQuiver.Build (HCompSet T) (fun A B => @HComp_hom T A B). + +(* HCompSet identity, defined in proof mode *) +Program Definition HComp_id_P (T: UFunctor.type) (A: HCompSet T) : A ~> A. +unfold hom; simpl. +unfold HComp_hom, C2Hom; simpl. +destruct A; simpl. +set h0' := HO h_first0. +set h1' := HO h_second0. +repeat econstructor. +instantiate (1:= @idmap (HHomSet T) h1'). +instantiate (1:= @idmap (HHomSet T) h0'). +assert (HC2Target (@idmap (HHomSet T) h0') = @idmap _ h_two0) as T0. +{ unfold HC2Target, HTarget. + rewrite F1; auto. +} +assert (HC2Source (@idmap (HHomSet T) h1') = @idmap _ h_two0) as S1. +{ unfold HC2Source, HSource. + rewrite F1; auto. +} +rewrite T0. +rewrite S1. +reflexivity. +Defined. + +(* HCompSet identity, only partially in proof mode *) +Program Definition HComp_id (T: UFunctor.type) (A: HCompSet T) : A ~> A := + let h0 := h_first A + in let h1 := h_second A + in let uu0 := @idmap (HHomSet T) (HO h0) + in let uu1 := @idmap (HHomSet T) (HO h1) + in @existT (C2Hom h0 h0) + (fun hh0: (C2Hom h0 h0) => + sigma (hh1 : C2Hom h1 h1), HC2Target hh0 = HC2Source hh1) uu0 + (@existT (C2Hom h1 h1) + (fun hh1: (C2Hom h1 h1) => HC2Target uu0 = HC2Source hh1) uu1 _). +Obligation 1. +unfold HC2Target, HTarget. +unfold HC2Source, HSource. +repeat rewrite F1; auto. +Defined. + +(* HCompSet composition, defined in proof mode *) +Program Definition HComp_comp (T: UFunctor.type) (A B C: HCompSet T) + (chA: A ~> B) (chB: B ~> C) : A ~> C. +destruct chA as [hhA0 pA]. +destruct chB as [hhB0 pB]. +destruct pA as [hhA1 ppA]. +destruct pB as [hhB1 ppB]. +set hh0 := comp hhA0 hhB0. +set hh1 := comp hhA1 hhB1. +econstructor 1 with (x:=hh0). +econstructor 1 with (x:=hh1). +set vv := comp (HC2Target hhA0) (HC2Target hhB0). +assert (comp (HC2Source hhA1) (HC2Source hhB1) = vv) as vv_E. +{ rewrite <- ppA. + rewrite <- ppB. + subst vv; auto. +} +assert (HC2Target hh0 = vv) as vv_ET. +{ subst vv. + unfold HC2Target, HTarget. + rewrite Fcomp; auto. +} +assert (HC2Source hh1 = vv) as vv_ES. +{ rewrite <- vv_E. + unfold HC2Source, HSource. + rewrite Fcomp; auto. +} +rewrite vv_ET. +rewrite vv_ES. +reflexivity. +Defined. + +(* HCompSet gives a precategory *) +HB.instance Definition HCompPreCat (T: UFunctor.type) : + Quiver_IsPreCat (HCompSet T) := + Quiver_IsPreCat.Build (HCompSet T) + (@HComp_id T) (@HComp_comp T). + +(* TODO: to be replaced by a proof *) +Global Parameter GCompAx : forall (T: UFunctor.type), + PreCat_IsCat (HCompSet T). + +HB.instance Definition HCompCat (T: UFunctor.type) := GCompAx T. + +(* composition prefunctor *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsCPreFunctor T of UFunctor T := + { is_cprefunctor : IsPreFunctor (HCompSet T) (HHomSet T) (@HComp T) }. +HB.structure Definition CPreFunctor : Set := {C of IsCPreFunctor C}. +Set Universe Checking. + +(* composition functor *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record CPreFunctor_IsFunctor T of CPreFunctor T := { + is_cfunctor : PreFunctor_IsFunctor (HCompSet T) (HHomSet T) (@HComp T) }. +HB.structure Definition CFunctor : Set := {C of CPreFunctor_IsFunctor C}. +Set Universe Checking. + +(* horizontal 2-cell composition: maps two adjecent pairs of + horizontal morphisms (a and b) and a pullback-category morphism + between them (m, which basically gives two adjecent cells) to a + 2-cell morphism between the horizontal composition (HComp) of each + pair *) +Definition HC2Comp (T: CFunctor.type) (a b: HCompSet T) + (m: @hom (HCompSet T) a b) : + c2hom (HComp a) (HComp b) := @Fhom _ _ (@HComp T) a b m. + + +(* Double category with strong horizontal unit (Russ' paper). + hunit defines proper identity on horizontal morphisms *) +HB.mixin Record IsDCat_SU T of CFunctor T := { + left_unital : forall (a0 a1: T) (h : hhom a0 a1), + @hcomp T a0 a0 a1 (hunit a0) h = h ; + + right_unital : forall (a0 a1: T) (h : hhom a0 a1), + @hcomp T a0 a1 a1 h (hunit a1) = h ; +}. +Unset Universe Checking. +#[short(type="dcat_su")] +HB.structure Definition DCat_SU : Set := { C of IsDCat_SU C }. +Set Universe Checking. + +(* Double category with weak horizontal unit (display paper) *) +HB.mixin Record IsDCat_WU T of CFunctor T := { + left_unital : forall (a0 a1: T) (h : hhom a0 a1), + let hh := HO h + in let uh := HO (hcomp a0 a0 a1 (hunit a0) h) + in exists uhc : c2hom uh hh, + HC2Source uhc = @idmap T a0 /\ + HC2Target uhc = @idmap T a1 ; + + right_unital : forall (a0 a1: T) (h : hhom a0 a1), + let hh := HO h + in let uh := HO (hcomp a0 a1 a1 h (hunit a1)) + in exists uhc : c2hom uh hh, + HC2Source uhc = @idmap T a0 /\ + HC2Target uhc = @idmap T a1 +}. +Unset Universe Checking. +#[short(type="dcat_wu")] +HB.structure Definition DCat_WU : Set := { C of IsDCat_WU C }. +Set Universe Checking. + +(* Double category with universal characterization of half-strong + horizontal unit *) +HB.mixin Record IsDCat_HU T of CFunctor T := { + left_unital : forall (a0 a1 b0 b1: T) + (r: @hhom T a0 a1) (s: @hhom T b0 b1), + let rr := @HO T (@hhom T) a0 a1 r in + let ss := @HO T (@hhom T) b0 b1 s in + let aa := @hunit T a0 in + let bb := @hunit T b0 in + @hom (HHomSet T) rr ss = + @hom (HHomSet T) (hhcomp (@GC T _ a0 a0 a1 aa r)) + (hhcomp (@GC T _ b0 b0 b1 bb s)) ; + + right_unital : forall (a0 a1 b0 b1: T) + (r: @hhom T a0 a1) (s: @hhom T b0 b1), + let rr := @HO T (@hhom T) a0 a1 r in + let ss := @HO T (@hhom T) b0 b1 s in + let aa := @hunit T a1 in + let bb := @hunit T b1 in + @hom (HHomSet T) rr ss = + @hom (HHomSet T) (hhcomp (@GC T _ a0 a1 a1 r aa)) + (hhcomp (@GC T _ b0 b1 b1 s bb)) ; +}. +Unset Universe Checking. +#[short(type="dcat_hu")] +HB.structure Definition DCat_HU : Set := { C of IsDCat_HU C }. +Set Universe Checking. + +(* Double category with weak horizontal associativity (display paper) *) +HB.mixin Record IsDCat_WA T of CFunctor T := { + associator : forall (a0 a1 a2 a3: T) + (h1: @hhom T a0 a1) (h2: @hhom T a1 a2) + (h3: @hhom T a2 a3) (x: HHomSet T), + let h12 := hcomp a0 a1 a2 h1 h2 in + let h23 := hcomp a1 a2 a3 h2 h3 in + let hh1 := HO (hcomp a0 a1 a3 h1 h23) in + let hh2 := HO (hcomp a0 a2 a3 h12 h3) in + exists asc: + c2hom hh1 hh2, HC2Source asc = @idmap T a0 /\ + HC2Target asc = @idmap T a3 +}. +Unset Universe Checking. +#[short(type="dcat_wa")] +HB.structure Definition DCat_WA : Set := { C of IsDCat_WA C }. +Set Universe Checking. +(* + a0 -- h0 --> a1 -- h1 --> a2 + | | | | | + v0 hh0 v1 hh1 v2 + | | | | | + V V V V V + b0 -- k0 --> b1 -- k1 --> b2 +*) + +(* Double category with universal characterization of weak + horizontal associativity *) +HB.mixin Record IsDCat_UA T of CFunctor T := { + associator : forall (a0 a1 a2 a3: T) + (h1: @hhom T a0 a1) (h2: @hhom T a1 a2) + (h3: @hhom T a2 a3) (x: HHomSet T), + let h23 := hcomp a1 a2 a3 h2 h3 in + let h12 := hcomp a0 a1 a2 h1 h2 in + let hh1 := hcomp a0 a1 a3 h1 h23 in + let hh2 := hcomp a0 a2 a3 h12 h3 in + @hom (HHomSet T) (@HO T (@hhom T) a0 a3 hh1) x = + @hom (HHomSet T) (@HO T (@hhom T) a0 a3 hh2) x + }. +(* +HB.mixin Record IsDCat_UA' T of CFunctor T := { + associator : forall (a0 a1 a2 a3: T) + (h1: @hhom T a0 a1) (h2: @hhom T a1 a2) + (h3: @hhom T a2 a3), + let h23 := hcomp a1 a2 a3 h2 h3 in + let h12 := hcomp a0 a1 a2 h1 h2 in + let hh1 := hcomp a0 a1 a3 h1 h23 in + let hh2 := hcomp a0 a2 a3 h12 h3 in + @hom (HHomSet T) (@HO T (@hhom T) a0 a3 hh2) + (@HO T (@hhom T) a0 a3 hh1) +}. +*) +Unset Universe Checking. +#[short(type="dcat_ua")] +HB.structure Definition DCat_UA : Set := { C of IsDCat_UA C }. +Set Universe Checking. + +(* double category, closer to the display paper *) +Unset Universe Checking. +#[short(type="dcat_dp")] +HB.structure Definition DCat_DP : Set := { C of DCat_WU C & DCat_WA C }. +Set Universe Checking. + +(* double category, closer to (my understanding of) Russ' paper *) +Unset Universe Checking. +#[short(type="dcat_rp")] +HB.structure Definition DCat_RP : Set := { C of DCat_SU C & DCat_UA C }. +Set Universe Checking. + + +(*********************************************************************) + +Program Definition HC2Comp_flat (T: CFunctor.type) (a0 a1 a2 b0 b1 b2: T) + (h0: hhom a0 a1) (h1: hhom a1 a2) + (k0: hhom b0 b1) (k1: hhom b1 b2) + (hh0: C2Hom h0 k0) + (hh1: C2Hom h1 k1) + (k: HC2Target hh0 = HC2Source hh1) + : (* C2Hom (hcomp _ _ _ h0 h1) (hcomp _ _ _ k0 k1) *) + c2hom (l_hcomp h0 h1) (l_hcomp k0 k1) := + @Fhom _ _ (@HComp T) (GC h0 h1) (GC k0 k1) _. +Obligation 1. +refine (@existT (C2Hom h0 k0) _ hh0 (@existT (C2Hom h1 k1) _ hh1 k)). +Defined. + +(* not working yet *) +HB.mixin Record IsDCat_U2 T of CFunctor T := { + left_unital : forall (a0 a1 b0 b1: T) (m: @hom T a0 b0) + (h : hhom a0 a1) (k : hhom b0 b1) + (hh: c2hom (HO h) (HO k)), + forall (xx: c2hom (HUnit a0) (HUnit b0)), + xx = HC2Unit m -> + HC2Source hh = m -> + @HC2Comp_flat T a0 a0 a1 b0 b0 b1 (hunit a0) h (hunit b0) k xx hh = + @HC2Comp_flat T a0 a0 a1 b0 b0 b1 (hunit a0) h (hunit b0) k xx hh +}. + + diff --git a/theories/encatD.v b/theories/encatD.v new file mode 100644 index 000000000..2ad0c7d4b --- /dev/null +++ b/theories/encatD.v @@ -0,0 +1,1129 @@ +Require Import ssreflect ssrfun. +Unset Universe Checking. +From HB Require Import structures cat. +Set Universe Checking. +Require Import Coq.Program.Equality. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. +Add Search Blacklist "__canonical__". + +Local Open Scope algebra_scope. + +Local Open Scope cat_scope. + +(* +Notation "'sigma' x .. y , p" := + (sigT (fun x => .. (sigT (fun y => p)) ..)) + (at level 200, x binder, right associativity, + format "'[' 'sigma' '/ ' x .. y , '/ ' p ']'") + : type_scope. +*) + +(********************************************************************) + +(*** INTERNAL CATEGORIES assuming products *) +(* based on the NLab definition at + https://ncatlab.org/nlab/show/internal+category +*) + +(* category extended with internal objects *) +HB.mixin Record HasIObjects C of Cat C := { + Obj : C ; + Mor : C +}. +HB.structure Definition IObjects := + { C of HasIObjects C }. + +(* operators (meant to abstract over pullbacks and pushouts*) +HB.mixin Record HasPOps C of IObjects C := { + prd : C -> C -> C ; + prj1 : forall c1 c2, prd c1 c2 ~> c1 ; + prj2 : forall c1 c2, prd c1 c2 ~> c2 ; + mprd : forall c1 c2 c3 c4, + (c1 ~> c3) -> (c2 ~> c4) -> prd c1 c2 ~> prd c3 c4 ; + mjn : forall c1 c2 c3, + (c1 ~> c2) -> (c1 ~> c3) -> c1 ~> prd c2 c3 +}. +HB.structure Definition POps := + { C of HasPOps C }. + +(* category extended with internal morphisms *) +HB.mixin Record IsIQuiver C of POps C := { + iid : Obj ~>_C Mor ; + isrc : Mor ~>_C Obj ; + itrg : Mor ~>_C Obj ; + icmp : @prd C Mor Mor ~> Mor +}. +HB.structure Definition IQuiver := + { C of IsIQuiver C }. + +Notation idO C := (@idmap C Obj). +Notation idM C := (@idmap C Mor). +Notation prdMM := (prd Mor Mor). +Notation prdPM := (prd (prd Mor Mor) Mor). +Notation prjMM1 := (prj1 Mor Mor). +Notation prjMM2 := (prj2 Mor Mor). +Notation prjOM1 := (prj1 Obj Mor). +Notation prjOM2 := (prj2 Obj Mor). +Notation prjMO1 := (prj1 Mor Obj). +Notation prjMO2 := (prj2 Mor Obj). +Notation prjPM1 := (prj1 (prd Mor Mor) Mor). +Notation prjPM2 := (prj2 (prd Mor Mor) Mor). +Notation prjPM1_ C := (@prj1 C (prd Mor Mor) Mor). +Notation prjPM2_ C := (@prj2 C (prd Mor Mor) Mor). +Notation prjMP1 := (prj1 Mor (prd Mor Mor)). +Notation prjMP2 := (prj2 Mor (prd Mor Mor)). +Notation mprdOMMM := (mprd Obj Mor Mor Mor). +Notation mprdMOMM := (mprd Mor Obj Mor Mor). +Notation mprdPMMM := (mprd (prd Mor Mor) Mor Mor Mor). +Notation mprdMPMM := (mprd Mor (prd Mor Mor) Mor Mor). + +(* internal quiver extended with the required pullback properties *) +HB.mixin Record IsIPreCat C of IQuiver C := { + pbkMM : prjMM2 \; @isrc C = prjMM1 \; itrg ; + pbkPMcmp : prjPM2 \; @isrc C = prjPM1 \; icmp \; itrg ; + pbkMPcmp : prjMP2 \; @icmp C \; isrc = prjMP1 \; itrg ; + pbkPM : prjPM2 \; @isrc C = prjPM1 \; prjMM2 \; itrg ; + pbkMP : prjMP2 \; prjMM1 \; @isrc C = prjMP1 \; itrg ; + pbkPM2MM1 : prjPM1_ C \; prjMM2 = + mjn prdPM Mor Mor (prjPM1 \; prjMM2) prjPM2 \; prjMM1 ; + pbkPM2MM2 : prjPM2_ C = + mjn prdPM Mor Mor (prjPM1 \; prjMM2) prjPM2 \; prjMM2 ; + pbkPM2MP1 : prjPM1_ C \; prjMM1 = + mjn prdPM Mor prdMM (prjPM1 \; prjMM1) + (mjn prdPM Mor Mor (prjPM1 \; prjMM2) prjPM2) \; prjMP1 ; + pbkPM2MP2 : mjn prdPM Mor Mor (prjPM1_ C \; prjMM2) prjPM2 = + mjn prdPM Mor prdMM (prjPM1 \; prjMM1) + (mjn prdPM Mor Mor (prjPM1 \; prjMM2) prjPM2) \; prjMP2 ; +}. +HB.structure Definition IPreCat := + { C of IsIPreCat C }. + +(* definition of internal category *) +HB.mixin Record IsICat C of IPreCat C := { + iid_s : iid \; isrc = idO C ; + iid_t : iid \; itrg = idO C ; + icmp_s : @icmp C \; isrc = prjMM1 \; isrc ; + icmp_t : @icmp C \; itrg = prjMM2 \; itrg ; + unit_l : mprdOMMM iid (idM C) \; icmp = prjOM2 ; + unit_r : mprdMOMM (idM C) iid \; icmp = prjMO1 ; + assoc : mprdPMMM icmp (idM C) \; icmp = + mjn prdPM Mor prdMM (prjPM1 \; prjMM1) + (mjn prdPM Mor Mor (prjPM1 \; prjMM2) prjPM2) \; + mprdMPMM (idM C) icmp \; icmp +}. +HB.structure Definition ICat := + { C of IsICat C }. +(* +HB.mixin Record IsICat C of IQuiver C := { + iid_s : iid \; isrc = @idmap C Obj ; + iid_t : iid \; itrg = @idmap C Obj ; + icmp_s : @icmp C \; isrc = prj1 Mor Mor \; isrc ; + icmp_t : @icmp C \; itrg = prj2 Mor Mor \; itrg ; + unit_l : mprd Obj Mor Mor Mor iid (@idmap C Mor) \; icmp = + prj2 Obj Mor ; + unit_r : mprd Mor Obj Mor Mor (@idmap C Mor) iid \; icmp = + prj1 Mor Obj ; + assoc : mprd (prd Mor Mor) Mor Mor Mor icmp (@idmap C Mor) + \; icmp = + (mjn (prd (prd Mor Mor) Mor) Mor (prd Mor Mor) + (prj1 (prd Mor Mor) Mor \; prj1 Mor Mor) + (mjn (prd (prd Mor Mor) Mor) Mor Mor + (prj1 (prd Mor Mor) Mor \; prj2 Mor Mor) + (prj2 (prd Mor Mor) Mor))) \; + (mprd Mor (prd Mor Mor) Mor Mor (@idmap C Mor) icmp) + \; icmp +}. +*) + +(********************************************************************) + +(*** GENERALISED ENRICHED CATEGORIES *) + +Declare Scope encat_scope. +Delimit Scope encat_scope with encat. +Local Open Scope encat_scope. + +(* Enrichment in a monoidal category, following + https://ncatlab.org/nlab/show/enriched+category +*) +HB.mixin Record IsEnQuiver (V: Type) C := { + hom_object : C -> C -> V + }. +Unset Universe Checking. +HB.structure Definition EnQuiver (V: Type) : Set := + { C of IsEnQuiver V C }. +Set Universe Checking. + +(* Monoidal precategory with the enrichment operators (no axioms) *) +HB.mixin Record IsEnPreCat (V: PreMonoidal.type) C of + EnQuiver (PreMonoidal.sort V) C := { + id_element : forall (a: C), + @hom V onec (hom_object a a) ; + comp_morphism : forall (a b c: C), + @hom V (@hom_object V C b c * @hom_object V C a b) + (@hom_object V C a c) +}. +Unset Universe Checking. +HB.structure Definition EnPreCat (V: PreMonoidal.type) : Set := + { C of IsEnPreCat V C }. +Set Universe Checking. + +Notation "a ~^ b" := (hom_object a b) + (at level 99, b at level 200, format "a ~^ b") : encat_scope. +Notation "a ~^_ ( V , C ) b" := (@hom_object V C a b) + (at level 99, V at level 0, C at level 0, only parsing) : cat_scope. +Notation "~^IE a" := (id_element a) + (at level 99, format "~^IE a") : cat_scope. +Notation "~^IE_ ( V , C ) a" := (@id_element V C a) + (at level 99, V at level 0, C at level 0, only parsing) : cat_scope. +(* not working *) +Notation "~^CM a b c" := (comp_morphism a b c) + (at level 99, + format "~^CM a b c") : cat_scope. +Notation "~^CM_ ( V , C ) a b c" := (@comp_morphism V C a b c) + (at level 99, V at level 0, C at level 0, only parsing) : cat_scope. + +(* V-enriched category: + V is the monoidal category; + C is the base category that gets enriched +*) +HB.mixin Record IsEnCat (V: Monoidal.type) C of EnPreCat V C := { + ecat_comp_assoc : forall a b c d: C, + forall alpha: + (((c ~^_(V,C) d) * (b ~^_(V,C) c)) * (a ~^_(V,C) b)) ~>_V + ((c ~^_(V,C) d) * ((b ~^_(V,C) c) * (a ~^_(V,C) b))), + ((@comp_morphism V C b c d) <*> (@idmap V (a ~^_(V,C) b))) \; + (@comp_morphism V C a b d) + = + alpha \; + ((@idmap V (c ~^_(V,C) d)) <*> (@comp_morphism V C a b c)) \; + (@comp_morphism V C a c d) ; + + ecat_comp_left_unital : forall a b: C, + forall l: onec * (a ~^_(V,C) b) ~>_V (a ~^_(V,C) b), + l = ((@id_element V C b) <*> (@idmap V (a ~^_(V,C) b))) \; + (@comp_morphism V C a b b) ; + ecat_comp_right_unital : forall a b: C, + forall r: (a ~^_(V,C) b) * onec ~>_V (a ~^_(V,C) b), + r = ((@idmap V (a ~^_(V,C) b)) <*> (@id_element V C a)) \; + (@comp_morphism V C a a b) +}. +Unset Universe Checking. +#[verbose] +HB.structure Definition EnCat (V: Monoidal.type) : Set := + { C of IsEnCat V C }. +Set Universe Checking. + +(********************************************************************) + +(*** DOUBLE CATEGORIES (without internal categories, with H0) *) + +(* Strict double categories, from + https://ncatlab.org/nlab/show/double+category + (we don't use internal categories) + + base obejcts as 0-cells: C ; + + vertical 1-morphisms (category D0 on C): hom C ; + + horizontal 1-morphisms (category H on C): hom (transpose C) ; + + horizontal 1-morhisms as 1-cells for D1: D1obj C ; + + 2-morphisms (category D1 on D1obj): hom (D1obj C) ; + + horizontally composable pairs of 1-cells : DPobj C ; + + horizontally composable pairs of 2-morphisms + (product category DP, D1 *0 D1) : hom (DPobj C) ; + + The definition of Strict Double Category, SDouble = (D0, H, D1, Dp), + is given by: + + - base objects C + + - (level-1) category (D0) of vertical 1-morphism on C + + - (level-1) category (H) of horizontal 1-morphism (D1obj) on C + + - (level-2) category (D1) of vertical 2-morphism on D1obj + + - (derived) category (DP) of vertical 2-morphisms on + horizontally D0-composable D1 products + ($\mbox{D1} *_0 \mbox{D1}$) + + - Source functor: D1 -> D0 + + - Target functor: D1 -> D0 + + - Horizontal unit functor: D0 -> D1 + + - Horizontal composition functor: DP -> D1 + + - First DP projection: DP -> D1 + + - Second DP projection: DP -> D1 +*) + + +(** Quivers for double categories *) + +(* transpose for horizontal morphism quiver. + HB.tag needed to identify transpose as lifter *) +HB.tag Definition transpose (C : quiver) : U := C. + +(* vertical and horizontal quivers, defining cells *) +#[short(type="vhquiver"),unsafe(univ)] +HB.structure Definition VHQuiver : Set := + { C of IsQuiver C & IsQuiver (transpose C) }. + +HB.tag Definition hhom (c : VHQuiver.type) : c -> c -> U := @hom (transpose c). +Notation "a +> b" := (hhom a b) + (at level 99, b at level 200, format "a +> b") : cat_scope. + +(* record to represent the set of morphims + (needed for 2-objects, i.e. horizontal morphisms) *) +Record Total2 T (h: T -> T -> U) : Type := TT2 { + source : T; + target : T; + this_morph : h source target }. + +(* the set of horizontal morphisms. *) +HB.tag Definition D1obj (C: vhquiver) := Total2 (@hhom C). + +(* D1 quiver requirement (includes D0 quiver and its transpose). *) +#[short(type="dquiver"),unsafe(univ)] +HB.structure Definition DQuiver : Set := { C of IsQuiver (D1obj C) }. + +(** Horizonal D0-level category (H-D0) *) + +(* Precategory based on the HQuiver (i.e. horizontal precategory on D0 + objects) *) +#[short(type="hprecat"),unsafe(univ)] +HB.structure Definition HPreCat : Set := + { C of Quiver_IsPreCat (transpose C) }. + +(* The category based on the HQuiver (i.e. horizontal category on D0 + objects) *) +#[short(type="hcat"),unsafe(univ)] +HB.structure Definition HCat : Set := + { C of HPreCat C & PreCat_IsCat (transpose C) }. + +(** Vertical 2-cell level category (D1 category) *) + +(* Precategory based on the DQuiver (i.e. precategory D1). Gives: + vertical 2-cell identity morphism. + vertical 2-cell composition. *) + HB.status. +#[short(type="d1precat"),unsafe(univ)] +HB.structure Definition D1PreCat : Set := + { C of Quiver_IsPreCat (D1obj C) }. + +x +(* The category based on the DQuiver (i.e. category D1). *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record _IsD1Cat T of D1PreCat T := { + is_d1cat : PreCat_IsCat (@D1obj T) }. +#[short(type="d1cat")] +HB.structure Definition D1Cat : Set := + { C of PreCat_IsCat (@D1obj C) }. +Set Universe Checking. + + +(** Naked double category *) + +(* Naked double category. Vertical (V-D0) and D1 categories. Double + category without horizontal operators and functors *) +Unset Universe Checking. +#[short(type="dcat")] +HB.structure Definition DCat : Set := + { C of Cat C & D1Cat C }. +Set Universe Checking. + +(* Naked strict double category. Vertical (V-D0), horizontal (H-D0) + and D1 categories. Strict double category without functors *) +Unset Universe Checking. +#[short(type="sd2cat")] +HB.structure Definition SDCat : Set := { C of Cat C & HCat C & D1Cat C }. +Set Universe Checking. + + +(** Auxiliary notions for Source, Target and + Horizontal Unit functors *) + +(* homsets of 2-cell (D1) morphisms *) +Definition d1hom (D: DQuiver.type) : D1obj D -> D1obj D -> U := + @hom (D1obj D). +(* type-level smart constructor for D1 homsets *) +Definition D1hom (D: DQuiver.type) (a b c d: D) (h0: hhom a b) + (h1: hhom c d) : U := d1hom (TT2 h0) (TT2 h1). + +(* smart projections for: + source functor (for horizontal morphisms): D1 -> D0. + defined as object-level function, by functoriality lifted to a + (2-cell, vertical) morphism-level one *) +HB.tag Definition HSource C := fun (X: D1obj C) => @source C (@hhom C) X. +(* target functor (for horizontal morphisms): D1 -> D0. *) +HB.tag Definition HTarget C := fun (X: D1obj C) => @target C (@hhom C) X. + +(* horizontal unit functor: D0 -> D1 *) +Definition hhunit (T: hprecat) (a: T) : D1obj T := + @TT2 T (@hhom T) a a (@idmap (transpose T) a). +HB.tag Definition H1Unit (C: hprecat) := + fun (x: HPreCat.sort C) => @hhunit C x. + + +(** Auxiliary notions for 2-cell Horizontal Composition functor *) + +(* composable pairs of morphisms as a set *) +Record GenComp T (h: T -> T -> U) := GC { + h_one : T; + h_two : T ; + h_three : T; + h_first : h h_one h_two ; + h_second : h h_two h_three }. + +(* composable pairs of horizontal morphisms as a set *) +HB.tag Definition DPobj (C: vhquiver) := GenComp (@hhom C). + +(* smart projections *) +Definition H2First (C: vhquiver) (X: @DPobj C) : D1obj C := + @TT2 C _ (h_one X) (h_two X) (h_first X). +Definition H2Second (C: vhquiver) (X: @DPobj C) : D1obj C := + @TT2 C _ (h_two X) (h_three X) (h_second X). + + +(* horizontal composition functor: D1 * D1 -> D1 *) +Definition hhcomp (T: hprecat) (x: DPobj T) : D1obj T := + match x with + @GC _ _ a b c h1 h2 => @TT2 T (@hhom T) a c (h1 \; h2) end. +HB.tag Definition H1Comp (C: hprecat) := + fun (x: DPobj C) => @hhcomp C x. + +(* hhunit - horizontal unit functor. + + hhcomp - horizontal composition functor (horizontal composition of + two horizontal morphisms from a cell product). + + Both specified as object-level functions (they actually come for + free from the H-D0 category, since we are in the strict case), to + be lifted by functoriality to morphism-level ones. + + At the object level, hhunit gives a horizontal identity morphism + for each D0 object. At the morphism level, it gives horizontal + 2-cell identity for each vertical morphism. + + In the case of hhcomp, relying on functoriality requires some care + in defining the product category, making sure that adjacency at the + object-level (between horizontal morphisms) is matched by adjacency + at the morphism-level (between 2-cells). *) + + +(** Source and target functors *) + +(* source prefunctor. + D1obj T is the quiver of the 2-morphisms, thanks to VHQuiver. + T is the quiver of 1-morphisms. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsSPreFunctor T of DCat T := { + is_sprefunctor : IsPreFunctor (D1obj T) T (@HSource T) }. +HB.structure Definition SPreFunctor : Set := {C of IsSPreFunctor C}. +Set Universe Checking. + +(* target prefunctor. *) +Unset Universe Checking. +#[wrapper] + HB.mixin Record IsTPreFunctor T of DCat T := { + is_tprefunctor : IsPreFunctor (D1obj T) T (@HTarget T) }. +HB.structure Definition TPreFunctor : Set := {C of IsTPreFunctor C}. +Set Universe Checking. + +(* source functor. *) +Unset Universe Checking. +#[wrapper] + HB.mixin Record SPreFunctor_IsFunctor T of SPreFunctor T := { + is_sfunctor : PreFunctor_IsFunctor (D1obj T) T (@HSource T) }. +HB.structure Definition SFunctor : Set := {C of SPreFunctor_IsFunctor C}. +Set Universe Checking. + +(* target functor. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record TPreFunctor_IsFunctor T of TPreFunctor T := { + is_tfunctor : PreFunctor_IsFunctor (D1obj T) T (@HTarget T) }. +HB.structure Definition TFunctor : Set := {C of TPreFunctor_IsFunctor C}. +Set Universe Checking. + + +(** Unit functor *) + +(* unit prefunctor. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsUPreFunctor T of SDCat T := + { is_uprefunctor : IsPreFunctor T (D1obj T) (@H1Unit T) }. +HB.structure Definition UPreFunctor : Set := {C of IsUPreFunctor C}. +Set Universe Checking. + +(* unit functor. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record UPreFunctor_IsFunctor T of UPreFunctor T := { + is_ufunctor : PreFunctor_IsFunctor T (D1obj T) (@H1Unit T) }. +HB.structure Definition UFunctor : Set := {C of UPreFunctor_IsFunctor C}. +Set Universe Checking. + +Unset Universe Checking. +(* HB.about Functor. *) +HB.structure Definition STUFunctor : Set := + {C of SFunctor C & TFunctor C & UFunctor C}. +Set Universe Checking. + + +(** Lifting of Source, Target and Unit functors to D1 morphisms *) + +(* 2-cell source *) +Definition H1Source (T: SFunctor.type) (a b: @D1obj T) + (m: @d1hom T a b) : + (HSource a) ~> (HSource b) := (@HSource T) <$> m. + +(* 2-cell target *) +Definition H1Target (T: TFunctor.type) (a b: @D1obj T) + (m: @d1hom T a b) : + (HTarget a) ~> (HTarget b) := (@HTarget T) <$> m. + +(* horizontal 2-cell unit (maps vertical morphisms to horizontally + unitary 2-cells) *) +Definition H2Unit (T: UFunctor.type) (a b: T) (m: @hom T a b) : + (H1Unit a) ~> (H1Unit b) := (@H1Unit T) <$> m. + +(* DP objects source and target *) +Lemma DPsource (T: STUFunctor.type) (a: DPobj T) : + HSource (H1Comp a) = HSource (TT2 (h_first a)). + destruct a; simpl in *; simpl. + auto. +Defined. + +Lemma DPtarget (T: STUFunctor.type) (a: DPobj T) : + HTarget (H1Comp a) = HTarget (TT2 (h_second a)). + destruct a; simpl in *; simpl. + auto. +Defined. + +Lemma unit_source (T: STUFunctor.type) (a: T) : + HSource (H1Unit a) = a. + simpl in *; simpl; auto. +Defined. + +Lemma unit_target (T: STUFunctor.type) (a: T) : + HTarget (H1Unit a) = a. + simpl in *; simpl; auto. +Defined. + +(** Horizontal product category (D1 *d0 D1) *) +(* DPobj T is the pseudo-pullback category used to deal with + products of D1 (where the adjacency condition is expressed + w.r.t. D0 *) + +(* horizontal composition of two (naked) horizontal morphisms *) +Definition l_hcomp (T: SDCat.type) (a0 a1 a2: T) + (h0: hhom a0 a1) (h1: hhom a1 a2) : D1obj T := + @TT2 T _ a0 a2 (h0 \; h1). + +(* +Notation "'sigma' x .. y , p" := + (sigT (fun x => .. (sigT (fun y => p)) ..)) + (at level 200, x binder, right associativity, + format "'[' 'sigma' '/ ' x .. y , '/ ' p ']'") + : type_scope. +*) + +(** DPobj quiver *) +Definition DP_hom (T: STUFunctor.type) (x y: DPobj T) := + sigma (hh0: D1hom (h_first x) (h_first y)) + (hh1: D1hom (h_second x) (h_second y)), + H1Target hh0 = H1Source hh1. + +HB.instance Definition DPQuiver (T: STUFunctor.type) : + IsQuiver (DPobj T) := + IsQuiver.Build (DPobj T) (fun A B => @DP_hom T A B). + + +(** Product precategory *) + +Lemma DP_id_eq (T : STUFunctor.type) (a: DPobj T) : + H1Target (@idmap (@D1obj T) (H2First a)) = + H1Source (@idmap (@D1obj T) (H2Second a)). +unfold H1Target, HTarget. +unfold H1Source, HSource. +repeat rewrite F1; auto. +Defined. + +(* DPobj identity *) +Definition DP_id (T: STUFunctor.type) (A: DPobj T) : A ~> A := + let h0 := h_first A + in let h1 := h_second A + in let uu0 := @idmap (D1obj T) (TT2 h0) + in let uu1 := @idmap (D1obj T) (TT2 h1) + in @existT (D1hom h0 h0) + (fun hh0: (D1hom h0 h0) => + sigma (hh1 : D1hom h1 h1), H1Target hh0 = H1Source hh1) uu0 + (@existT (D1hom h1 h1) + (fun hh1: (D1hom h1 h1) => H1Target uu0 = H1Source hh1) uu1 + (@DP_id_eq T A)). + +Definition DP_comp_auxA (T : STUFunctor.type) + (A B C : DPobj T) + (hhA0 : D1hom (h_first A) (h_first B)) + (hhA1 : D1hom (h_second A) (h_second B)) + (ppA : H1Target hhA0 = H1Source hhA1) + (hhB0 : D1hom (h_first B) (h_first C)) + (hhB1 : D1hom (h_second B) (h_second C)) + (ppB : H1Target hhB0 = H1Source hhB1) : + (H1Target hhA0) \; (H1Target hhB0) = + (H1Source hhA1) \; (H1Source hhB1). + rewrite ppA. + rewrite ppB. + reflexivity. +Defined. + +Definition DP_comp_auxS (T : STUFunctor.type) + (A B C : DPobj T) + (hhA0 : D1hom (h_first A) (h_first B)) + (hhA1 : D1hom (h_second A) (h_second B)) + (ppA : H1Target hhA0 = H1Source hhA1) + (hhB0 : D1hom (h_first B) (h_first C)) + (hhB1 : D1hom (h_second B) (h_second C)) + (ppB : H1Target hhB0 = H1Source hhB1) : + H1Source (hhA1 \; hhB1) = (H1Source hhA1) \; (H1Source hhB1). + unfold H1Source, HSource. + repeat rewrite Fcomp. + reflexivity. +Defined. + +Definition DP_comp_auxT (T : STUFunctor.type) + (A B C : DPobj T) + (hhA0 : D1hom (h_first A) (h_first B)) + (hhA1 : D1hom (h_second A) (h_second B)) + (ppA : H1Target hhA0 = H1Source hhA1) + (hhB0 : D1hom (h_first B) (h_first C)) + (hhB1 : D1hom (h_second B) (h_second C)) + (ppB : H1Target hhB0 = H1Source hhB1) : + H1Target (hhA0 \; hhB0) = (H1Target hhA0) \; (H1Target hhB0). + unfold H1Target, HTarget. + repeat rewrite Fcomp. + reflexivity. +Defined. + +Definition DP_comp_auxI (T : STUFunctor.type) + (A B C : DPobj T) + (hhA0 : D1hom (h_first A) (h_first B)) + (hhA1 : D1hom (h_second A) (h_second B)) + (ppA : H1Target hhA0 = H1Source hhA1) + (hhB0 : D1hom (h_first B) (h_first C)) + (hhB1 : D1hom (h_second B) (h_second C)) + (ppB : H1Target hhB0 = H1Source hhB1) : + A ~> C. + econstructor 1 with (comp hhA0 hhB0). + econstructor 1 with (comp hhA1 hhB1). + setoid_rewrite DP_comp_auxS; eauto. + setoid_rewrite DP_comp_auxT; eauto. + eapply DP_comp_auxA; eauto. +Defined. + +(* DPobj composition, defined in proof mode *) +Definition DP_comp (T: STUFunctor.type) (A B C: DPobj T) : + (A ~> B) -> (B ~> C) -> A ~> C. + intros chA chB. + destruct chA as [hhA0 [hhA1 ppA]]. + destruct chB as [hhB0 [hhB1 ppB]]. + eapply DP_comp_auxI; eauto. +Defined. + +(* DPobj is a precategory *) +HB.instance Definition DPPreCat (T: STUFunctor.type) : + Quiver_IsPreCat (DPobj T) := + Quiver_IsPreCat.Build (DPobj T) (@DP_id T) (@DP_comp T). + +(* + have HcompP : + (a b : DPobj T) + (f g : a ~> b), + proj1T f = proj1t f -> + + -> + f = g. + + exists a b p, + fst f = a + f = (a,b,p) +*) + +(** Product category *) + +Lemma DP_LeftUnit_lemma (T : STUFunctor.type) : + forall (a b : DPobj T) (f : a ~> b), idmap \; f = f. + + move => a b [x [x0 e]] /=. + simpl in *. + unfold idmap; simpl. + unfold DP_id; simpl. + unfold comp; simpl. + unfold DP_comp_auxI; simpl. + + assert (idmap \; x = x) as A. + { rewrite comp1o; auto. } + + assert (idmap \; x0 = x0) as A0. + { rewrite comp1o; auto. } + + assert (H1Target (idmap \; x) = H1Source (idmap \; x0)) as B. + { rewrite A. + rewrite A0; auto. } + + destruct a eqn: aaa. + destruct b eqn: bbb. + simpl. + + assert (existT + (fun hh0 : D1hom h_first0 h_first1 => + sigma hh1 : D1hom h_second0 h_second1,H1Target hh0 = H1Source hh1) + (idmap \; x) + (existT + (fun hh1 : D1hom h_second0 h_second1 => + H1Target (idmap \; x) = H1Source hh1) + (idmap \; x0) + B) = + existT + (fun hh0 : D1hom h_first0 h_first1 => + sigma hh1 : D1hom h_second0 h_second1,H1Target hh0 = H1Source hh1) + x + (existT + (fun hh1 : D1hom h_second0 h_second1 => H1Target x = H1Source hh1) + x0 + e)) as C. + { revert B. + revert A. + revert A0. + generalize (idmap \; x) as v. + generalize (idmap \; x0) as v0. + intros v0 v A0. + rewrite A0. + intro A. + rewrite A. + intro B. + + assert (B = e) as BE. + { eapply Prop_irrelevance. } + + rewrite BE. + reflexivity. +} + + inversion aaa; subst. + rewrite [Morphisms.trans_sym_co_inv_impl_morphism _ _ _ _ _] + (Prop_irrelevance _ B). + eapply C. +Qed. + +Lemma DP_RightUnit_lemma (T : STUFunctor.type) : + forall (a b : DPobj T) (f : a ~> b), f \; idmap = f. + + move => a b [x [x0 e]] /=. + simpl in *. + unfold idmap; simpl. + unfold DP_id; simpl. + unfold comp; simpl. + unfold DP_comp_auxI; simpl. + + assert (x \; idmap = x) as A. + { rewrite compo1; auto. } + + assert (x0 \; idmap = x0) as A0. + { rewrite compo1; auto. } + + assert (H1Target (x \; idmap) = H1Source (x0 \; idmap)) as B. + { rewrite A. + rewrite A0; auto. } + + destruct a eqn: aaa. + destruct b eqn: bbb. + simpl. + + assert (existT + (fun hh0 : D1hom h_first0 h_first1 => + sigma hh1 : D1hom h_second0 h_second1, + H1Target hh0 = H1Source hh1) + (x \; idmap) + (existT + (fun hh1 : D1hom h_second0 h_second1 => + H1Target (x \; idmap) = H1Source hh1) + (x0 \; idmap) + B) = + existT + (fun hh0 : D1hom h_first0 h_first1 => + sigma hh1 : D1hom h_second0 h_second1, + H1Target hh0 = H1Source hh1) + x + (existT + (fun hh1 : D1hom h_second0 h_second1 => + H1Target x = H1Source hh1) + x0 + e)) as C. + { revert B. + revert A. + revert A0. + generalize (x \; idmap) as v. + generalize (x0 \; idmap) as v0. + intros v0 v A0. + rewrite A0. + intro A. + rewrite A. + intro B. + + assert (B = e) as BE. + { eapply Prop_irrelevance. } + + rewrite BE. + reflexivity. + } + + inversion aaa; subst. + rewrite [Morphisms.trans_sym_co_inv_impl_morphism _ _ _ _ _] + (Prop_irrelevance _ B). + eapply C. +Qed. + +Lemma DP_Assoc_lemma (T : STUFunctor.type) : + forall (a b c d : DPobj T) (f : a ~> b) (g : b ~> c) (h : c ~> d), + f \; g \; h = (f \; g) \; h. + intros. + remember f as f1. + remember g as g1. + remember h as h1. + destruct f as [x0 s0]. + destruct g as [x1 s1]. + destruct h as [x2 s2]. + destruct s0 as [y0 e0]. + destruct s1 as [y1 e1]. + destruct s2 as [y2 e2]. + simpl. + + set (x01 := comp x0 x1). + set (x12 := comp x1 x2). + set (x0_12 := comp x0 x12). + set (x01_2 := comp x01 x2). + set (y01 := comp y0 y1). + set (y12 := comp y1 y2). + set (y0_12 := comp y0 y12). + set (y01_2 := comp y01 y2). + + assert (x0_12 = x01_2) as X0. + { subst x0_12 x01_2. + rewrite compoA; eauto. } + assert (y0_12 = y01_2) as Y0. + { subst y0_12 y01_2. + rewrite compoA; eauto. } + + set (x01_t := comp (H1Target x0) (H1Target x1)). + set (x01_2_t := comp x01_t (H1Target x2)). + set (x12_t := comp (H1Target x1) (H1Target x2)). + set (x0_12_t := comp (H1Target x0) x12_t). + set (y01_s := comp (H1Source y0) (H1Source y1)). + set (y01_2_s := comp y01_s (H1Source y2)). + set (y12_s := comp (H1Source y1) (H1Source y2)). + set (y0_12_s := comp (H1Source y0) y12_s). + + assert (x01_t = y01_s) as E01. + { subst x01_t y01_s. + rewrite e0. + rewrite e1; auto. } + assert (x01_2_t = y01_2_s) as E01_2. + { subst x01_2_t y01_2_s. + rewrite E01. + rewrite e2; auto. } + assert (x12_t = y12_s) as E12. + { subst x12_t y12_s. + rewrite e1. + rewrite e2; auto. } + assert (x0_12_t = y0_12_s) as E0_12. + { subst x0_12_t y0_12_s. + rewrite E12. + rewrite e0; auto. } + + assert (x0_12_t = x01_2_t) as E02T. + { subst x0_12_t x01_2_t. + subst x12_t x01_t. + rewrite compoA; auto. } + assert (y0_12_s = y01_2_s) as E02S. + { subst y0_12_s y01_2_s. + subst y12_s y01_s. + rewrite compoA; auto. } + + unfold comp. + simpl. + unfold DP_comp. + simpl. + inversion Heqf1; subst. + clear H. + + unfold DP_comp_auxI; simpl. + + assert (H1Target (x0 \; x1 \; x2) = + H1Source (y0 \; y1 \; y2)) as KR. + { subst x0_12_t y0_12_s. + subst x12_t y12_s. + unfold H1Target. + repeat rewrite Fcomp; simpl. + unfold H1Target in E0_12. + rewrite E0_12. + unfold H1Source. + repeat rewrite Fcomp; simpl. + auto. + } + + assert (H1Target ((x0 \; x1) \; x2) = + H1Source ((y0 \; y1) \; y2)) as KL. + { subst x01_2_t y01_2_s. + subst x01_t y01_s. + unfold H1Target. + repeat rewrite Fcomp; simpl. + unfold H1Target in E01_2. + rewrite E01_2. + unfold H1Source. + repeat rewrite Fcomp; simpl. + auto. + } + + assert (existT + (fun hh0 : D1hom (h_first a) (h_first d) => + sigma hh1 : D1hom (h_second a) (h_second d), + H1Target hh0 = H1Source hh1) + (x0 \; x1 \; x2) + (existT + (fun hh1 : D1hom (h_second a) (h_second d) => + H1Target (x0 \; x1 \; x2) = H1Source hh1) + (y0 \; y1 \; y2) + KR) + = + existT + (fun hh0 : D1hom (h_first a) (h_first d) => + sigma hh1 : D1hom (h_second a) (h_second d), + H1Target hh0 = H1Source hh1) + ((x0 \; x1) \; x2) + (existT + (fun hh1 : D1hom (h_second a) (h_second d) => + H1Target ((x0 \; x1) \; x2) = H1Source hh1) + ((y0 \; y1) \; y2) + KL)) as KA. + { revert KL. + revert KR. + subst x0_12 x01_2 x12 x01. + subst y0_12 y01_2 y12 y01. + rewrite <- X0. + rewrite <- Y0. + intros KR KL. + + assert (KR = KL) as I1. + { eapply Prop_irrelevance. } + rewrite I1. + reflexivity. + } + + rewrite [Morphisms.trans_sym_co_inv_impl_morphism _ _ _ _ _] + (Prop_irrelevance _ KR). + + rewrite [Morphisms.trans_sym_co_inv_impl_morphism _ _ _ _ _] + (Prop_irrelevance _ KL). + eapply KA. +Qed. + +Program Definition DPCatP (T: STUFunctor.type) : + PreCat_IsCat (DPobj T). +econstructor. +eapply DP_LeftUnit_lemma; eauto. +eapply DP_RightUnit_lemma; eauto. +eapply DP_Assoc_lemma; eauto. +Qed. + +(* DPobj is a category *) +HB.instance Definition DPCat (T: STUFunctor.type) := DPCatP T. + + +(** Horizontal composition functor and strict double categories *) + +(* fst horizontal projection prefunctor *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsHFPreFunctor T of STUFunctor T := + { is_hfprefunctor : IsPreFunctor (DPobj T) (D1obj T) (@H2First T) }. +HB.structure Definition HFPreFunctor : Set := {C of IsHFPreFunctor C}. +Set Universe Checking. + +(* fst horizontal projection functor *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record HFPreFunctor_IsFunctor T of HFPreFunctor T := { + is_hffunctor : PreFunctor_IsFunctor (DPobj T) (D1obj T) (@H2First T) }. +HB.structure Definition HFFunctor : Set := {C of HFPreFunctor_IsFunctor C}. +Set Universe Checking. + +(* snd horizontal projection prefunctor *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsHSPreFunctor T of STUFunctor T := + { is_hsprefunctor : IsPreFunctor (DPobj T) (D1obj T) (@H2Second T) }. +HB.structure Definition HSPreFunctor : Set := {C of IsHSPreFunctor C}. +Set Universe Checking. + +(* snd horizontal projection functor *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record HSPreFunctor_IsFunctor T of HSPreFunctor T := { + is_hsfunctor : PreFunctor_IsFunctor (DPobj T) (D1obj T) (@H2Second T) }. +HB.structure Definition HSFunctor : Set := {C of HSPreFunctor_IsFunctor C}. +Set Universe Checking. + +(* composition prefunctor *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsCPreFunctor T of STUFunctor T := + { is_cprefunctor : IsPreFunctor (DPobj T) (D1obj T) (@H1Comp T) }. +HB.structure Definition CPreFunctor : Set := {C of IsCPreFunctor C}. +Set Universe Checking. + +(* composition functor *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record CPreFunctor_IsFunctor T of CPreFunctor T := { + is_cfunctor : PreFunctor_IsFunctor (DPobj T) (D1obj T) (@H1Comp T) }. +HB.structure Definition CFunctor : Set := {C of CPreFunctor_IsFunctor C}. +Set Universe Checking. + +(* All functors together *) +Unset Universe Checking. +HB.structure Definition FCFunctor : Set := + {C of HFFunctor C & HSFunctor C & CFunctor C}. +Set Universe Checking. + + +(* first and second projection from pairs of cells *) +Definition HH2First (T: HFFunctor.type) (a b: DPobj T) + (m: DP_hom a b) : H2First a ~> H2First b := (@H2First T) <$> m. + +Definition HH2Second (T: HSFunctor.type) (a b: DPobj T) + (m: DP_hom a b) : H2Second a ~> H2Second b := (@H2Second T) <$> m. + +(* +Definition HH2First (T: HFFunctor.type) (a b: DPobj T) + (m: @hom (DPobj T) a b) : H2First a ~> H2First b := (@H2First T) <$> m. + +Definition HH2Second (T: HSFunctor.type) (a b: DPobj T) + (m: @hom (DPobj T) a b) : H2Second a ~> H2Second b := (@H2Second T) <$> m. +*) + +(* horizontal 2-cell composition: maps two adjecent pairs of + horizontal morphisms (a and b) and a pullback-category morphism + between them (m, which basically gives two adjecent cells) to a + 2-cell morphism between the horizontal composition (HComp) of each + pair *) +Definition HC2Comp (T: CFunctor.type) (a b: DPobj T) + (m: DP_hom a b) : + d1hom (H1Comp a) (H1Comp b) := @Fhom _ _ (@H1Comp T) a b m. + +(* +Definition HC2Comp (T: CFunctor.type) (a b: DPobj T) + (m: @hom (DPobj T) a b) : + d1hom (H1Comp a) (H1Comp b) := @Fhom _ _ (@H1Comp T) a b m. +*) + +Program Definition HC2Comp_flat (T: CFunctor.type) (a0 a1 a2 b0 b1 b2: T) + (h0: hhom a0 a1) (h1: hhom a1 a2) + (k0: hhom b0 b1) (k1: hhom b1 b2) + (hh0: D1hom h0 k0) + (hh1: D1hom h1 k1) + (K: H1Target hh0 = H1Source hh1) : D1hom (h0 \; h1) (k0 \; k1) := + @Fhom _ _ (@H1Comp T) (GC h0 h1) (GC k0 k1) _. +Obligation 1. +refine (@existT (D1hom h0 k0) _ hh0 (@existT (D1hom h1 k1) _ hh1 K)). +Defined. + + +(* quasi-double category *) +Unset Universe Checking. +HB.mixin Record IsQDoubleCat T of FCFunctor T := { + unit_source : forall (a b: T) (m: hom a b), + H1Source (H2Unit m) = m ; + + unit_target : forall (a b: T) (m: hom a b), + H1Target (H2Unit m) = m ; +}. +#[short(type="qdoublecat")] +HB.structure Definition QDoubleCat : Set := + { C of IsQDoubleCat C }. +Set Universe Checking. + + +(* definition of strict double category *) +Unset Universe Checking. +HB.mixin Record IsSDoubleCat T of QDoubleCat T := { + source_comp_dist : forall (a b: DPobj T) (m: DP_hom a b), + TT2 (H1Source (HC2Comp m)) = TT2 (H1Source (HH2First m)) ; + + target_comp_dist : forall (a b: DPobj T) (m: DP_hom a b), + TT2 (H1Target (HC2Comp m)) = TT2 (H1Target (HH2Second m)) ; +}. +#[short(type="sdoublecat")] +HB.structure Definition SDoubleCat : Set := + { C of IsSDoubleCat C }. +Set Universe Checking. + +(* alternative definition of strict double category (display-style) *) +Unset Universe Checking. +HB.mixin Record IsSDoubleCat1 T of QDoubleCat T := { + source_comp_dist1 : forall (a0 a1 a2 b0 b1 b2: T) + (h0: hhom a0 a1) (h1: hhom a1 a2) + (k0: hhom b0 b1) (k1: hhom b1 b2) + (hh0: D1hom h0 k0) + (hh1: D1hom h1 k1) + (K: H1Target hh0 = H1Source hh1), + H1Source (HC2Comp_flat K) = H1Source hh0 ; + + target_comp_dist1 : forall (a0 a1 a2 b0 b1 b2: T) + (h0: hhom a0 a1) (h1: hhom a1 a2) + (k0: hhom b0 b1) (k1: hhom b1 b2) + (hh0: D1hom h0 k0) + (hh1: D1hom h1 k1) + (K: H1Target hh0 = H1Source hh1), + H1Target (HC2Comp_flat K) = H1Target hh1 ; +}. +#[short(type="sdoublecat1")] +HB.structure Definition SDoubleCat1 : Set := + { C of IsSDoubleCat1 C }. +Set Universe Checking. + + +(* hcomp (hm, hu) = prj1 (hm, hu) = hm + hcomp (hu, hm) = prj2 (hu, hm) = hm + (hm1 * hm2) * hm3 ~> hm1 * (hm2 * hm3) + +(* Double category with universal characterization of weak + horizontal associativity *) +HB.mixin Record IsDCat_UA T of CFunctor T := { + associator : forall (a0 a1 a2 a3: T) + (h1: @hhom T a0 a1) (h2: @hhom T a1 a2) + (h3: @hhom T a2 a3), + let h23 := hcomp a1 a2 a3 h2 h3 in + let h12 := hcomp a0 a1 a2 h1 h2 in + let hh1 := hcomp a0 a1 a3 h1 h23 in + let hh2 := hcomp a0 a2 a3 h12 h3 in + @hom (HHomSet T) (@HO T (@hhom T) a0 a3 hh2) + (@HO T (@hhom T) a0 a3 hh1) +}. +*) + diff --git a/theories/encatH.v b/theories/encatH.v new file mode 100644 index 000000000..e067152fe --- /dev/null +++ b/theories/encatH.v @@ -0,0 +1,1265 @@ +Require Import ssreflect ssrfun. +Unset Universe Checking. +From HB Require Import structures cat encatD. +Set Universe Checking. +Require Import Coq.Program.Equality. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. +Add Search Blacklist "__canonical__". + +Local Open Scope algebra_scope. + +Local Open Scope cat_scope. + +(* +Notation "'sigma' x .. y , p" := + (sigT (fun x => .. (sigT (fun y => p)) ..)) + (at level 200, x binder, right associativity, + format "'[' 'sigma' '/ ' x .. y , '/ ' p ']'") + : type_scope. +*) + +(********************************************************************) + +(*** DOUBLE CATEGORIES (without internal categories, with H1) *) + +(* Strict double categories, from + https://ncatlab.org/nlab/show/double+category + (we don't use internal categories) + + base obejcts as 0-cells: C ; + + vertical 1-morphisms (category D0 on C): hom C ; + + horizontal 1-morphisms (category H on C): hom (transpose C) ; + + horizontal 1-morhisms as 1-cells for D1: D1obj C ; + + vertical 1-morhisms as 1-cells for H1: H1obj C ; + + 2-morphisms (category D1 on D1obj): hom (D1obj C) ; + + horizontally composable pairs of 1-cells : DPobj C ; + + horizontally composable pairs of 2-morphisms + (product category DP, D1 *0 D1) : hom (DPobj C) ; + + The definition of Strict Double Category, SDouble = (D0, D1, Dp, H1), + is given by: + + - base objects C + + - (level-1) category (D0) of vertical 1-morphism on C + + - (level-2) category (D1) of vertical 2-morphism on D1obj + + - (derived) category (DP) of vertical 2-morphisms on + horizontally D0-composable D1 products + ($\mbox{D1} *_0 \mbox{D1}$) + + - (level-2) category (H1) of horizontal 12morphism on H1obj + + - Source functor: D1 -> D0 + + - Target functor: D1 -> D0 + + - Horizontal unit functor: D0 -> D1 + + - Horizontal composition functor: DP -> D1 + + - First DP projection: DP -> D1 + + - Second DP projection: DP -> D1 +*) + + +(** Quivers for double categories *) + +(* transpose for horizontal morphism quiver. + HB.tag needed to identify transpose as lifter *) +HB.tag Definition transpose (C : quiver) : U := C. +#[wrapper] HB.mixin Record _IsHQuiver C of IsQuiver C := { + is_hquiver : IsQuiver (transpose C) +}. +(* vertical and horizontal quivers, defining cells *) +Unset Universe Checking. +#[short(type="vhquiver")] +HB.structure Definition VHQuiver : Set := + { C of IsQuiver C & IsQuiver (transpose C) }. +Set Universe Checking. + +HB.tag Definition hhom (c : VHQuiver.type) : c -> c -> U := @hom (transpose c). +Notation "a +> b" := (hhom a b) + (at level 99, b at level 200, format "a +> b") : cat_scope. + +(* record to represent the set of morphims + (needed for 2-objects, i.e. horizontal morphisms) *) +Record Total2 T (h: T -> T -> U) : Type := TT2 { + source : T; + target : T; + this_morph : h source target }. + +(* the set of horizontal morphisms. *) +HB.tag Definition D1obj (C: vhquiver) := Total2 (@hhom C). + +(* D1 quiver requirement (includes D0 quiver and its transpose). *) +#[wrapper] +HB.mixin Record _IsDQuiver T of VHQuiver T := + { is_dquiver : Quiver (D1obj T) }. +Unset Universe Checking. +#[short(type="dquiver")] +HB.structure Definition DQuiver : Set := { C of Quiver (D1obj C) }. +Set Universe Checking. + + +(** Horizonal D0-level category (H-D0) *) +(* +(* Precategory based on the HQuiver (i.e. horizontal precategory on D0 + objects) *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record _IsHPreCat T of VHQuiver T := { + is_hprecat : Quiver_IsPreCat (transpose T) }. +#[short(type="hprecat")] +HB.structure Definition HPreCat : Set := + { C of Quiver_IsPreCat (transpose C) }. +Set Universe Checking. + +(* The category based on the HQuiver (i.e. horizontal category on D0 + objects) *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record _IsHCat T of HPreCat T := { + is_hcat : PreCat_IsCat (transpose T) }. +#[short(type="hcat")] +HB.structure Definition HCat : Set := + { C of PreCat_IsCat (transpose C) }. +Set Universe Checking. +*) + +(** Vertical 2-cell level category (D1 category) *) + +(* Precategory based on the DQuiver (i.e. precategory D1). Gives: + vertical 2-cell identity morphism. + vertical 2-cell composition. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record _IsD1PreCat T of DQuiver T := { + is_d1precat : Quiver_IsPreCat (@D1obj T) }. +#[short(type="d1precat")] +HB.structure Definition D1PreCat : Set := + { C of Quiver_IsPreCat (@D1obj C) }. +Set Universe Checking. + +(* The category based on the DQuiver (i.e. category D1). *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record _IsD1Cat T of D1PreCat T := { + is_d1cat : PreCat_IsCat (@D1obj T) }. +#[short(type="d1cat")] +HB.structure Definition D1Cat : Set := + { C of PreCat_IsCat (@D1obj C) }. +Set Universe Checking. + + +(** Naked double category *) + +(* Naked double category. Vertical (V-D0) and D1 categories. Double + category without horizontal operators and functors *) +Unset Universe Checking. +#[short(type="dcat")] +HB.structure Definition DCat : Set := + { C of Cat C & D1Cat C }. +Set Universe Checking. + + +(* composable pairs of morphisms as a set *) +Record GenComp T (h: T -> T -> U) := GC { + h_one : T; + h_two : T ; + h_three : T; + h_first : h h_one h_two ; + h_second : h h_two h_three }. + +(* composable pairs of horizontal morphisms as a set *) +HB.tag Definition DPobj (C: vhquiver) := GenComp (@hhom C). + + +HB.mixin Record IsHDQuiver T of DQuiver T := { + hunit : forall a: T, @hhom T a a ; + hcomp : forall (a b c: T), @hhom T a b -> @hhom T b c -> @hhom T a c; +}. +Unset Universe Checking. +#[short(type="hdquiver")] +HB.structure Definition HDQuiver : Set := { C of IsHDQuiver C }. +Set Universe Checking. + +Definition hhunit (T: hdquiver) (a: T) : D1obj T := + @TT2 T (@hhom T) a a (hunit a). +HB.tag Definition H1Unit (C: hdquiver) := + fun (x: HDQuiver.sort C) => @hhunit C x. + +(* horizontal composition of two horizontal morphisms from a + cell product *) +Definition hhcomp (T: hdquiver) (x: DPobj T) : D1obj T := + match x with + @GC _ _ a b c h1 h2 => @TT2 T (@hhom T) a c (hcomp a b c h1 h2) end. +HB.tag Definition H1Comp (C: hdquiver) := + fun (x: DPobj C) => @hhcomp C x. + + +(* +(* Naked double category. Vertical V-D0 + and V-D1 categories. Strict double category without functors *) +Unset Universe Checking. +#[short(type="sd2cat")] +HB.structure Definition SDCat : Set := { C of Cat C (* & HCat C *) & D1Cat C }. +Set Universe Checking. +*) + +(** Auxiliary notions for Source, Target and + Horizontal Unit functors *) + +(* homsets of 2-cell (D1) morphisms *) +Definition d1hom (D: DQuiver.type) : D1obj D -> D1obj D -> U := + @hom (D1obj D). +(* type-level smart constructor for D1 homsets *) +Definition D1hom (D: DQuiver.type) (a b c d: D) (h0: hhom a b) + (h1: hhom c d) : U := d1hom (TT2 h0) (TT2 h1). + +(* smart projections for: + source functor (for horizontal morphisms): D1 -> D0. + defined as object-level function, by functoriality lifted to a + (2-cell, vertical) morphism-level one *) +HB.tag Definition HSource C := fun (X: D1obj C) => @source C (@hhom C) X. +(* target functor (for horizontal morphisms): D1 -> D0. *) +HB.tag Definition HTarget C := fun (X: D1obj C) => @target C (@hhom C) X. + +(* +(* horizontal unit functor: D0 -> D1 *) +Definition hhunit (T: hprecat) (a: T) : D1obj T := + @TT2 T (@hhom T) a a (@idmap (transpose T) a). +HB.tag Definition H1Unit (C: hprecat) := + fun (x: HPreCat.sort C) => @hhunit C x. +*) + +(** Auxiliary notions for 2-cell Horizontal Composition functor *) + +(* smart projections *) +Definition H2First (C: vhquiver) (X: @DPobj C) : D1obj C := + @TT2 C _ (h_one X) (h_two X) (h_first X). +Definition H2Second (C: vhquiver) (X: @DPobj C) : D1obj C := + @TT2 C _ (h_two X) (h_three X) (h_second X). + +(* +(* horizontal composition functor: D1 * D1 -> D1 *) +Definition hhcomp (T: hprecat) (x: DPobj T) : D1obj T := + match x with + @GC _ _ a b c h1 h2 => @TT2 T (@hhom T) a c (h1 \; h2) end. +HB.tag Definition H1Comp (C: hprecat) := + fun (x: DPobj C) => @hhcomp C x. +*) + +(* hhunit - horizontal unit functor. + + hhcomp - horizontal composition functor (horizontal composition of + two horizontal morphisms from a cell product). + + Both specified as object-level functions (they actually come for + free from the H-D0 category, since we are in the strict case), to + be lifted by functoriality to morphism-level ones. + + At the object level, hhunit gives a horizontal identity morphism + for each D0 object. At the morphism level, it gives horizontal + 2-cell identity for each vertical morphism. + + In the case of hhcomp, relying on functoriality requires some care + in defining the product category, making sure that adjacency at the + object-level (between horizontal morphisms) is matched by adjacency + at the morphism-level (between 2-cells). *) + + +(** Source and target functors *) + +(* source prefunctor. + D1obj T is the quiver of the 2-morphisms, thanks to VHQuiver. + T is the quiver of 1-morphisms. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsSPreFunctor T of DCat T := { + is_sprefunctor : IsPreFunctor (D1obj T) T (@HSource T) }. +HB.structure Definition SPreFunctor : Set := {C of IsSPreFunctor C}. +Set Universe Checking. + +(* target prefunctor. *) +Unset Universe Checking. +#[wrapper] + HB.mixin Record IsTPreFunctor T of DCat T := { + is_tprefunctor : IsPreFunctor (D1obj T) T (@HTarget T) }. +HB.structure Definition TPreFunctor : Set := {C of IsTPreFunctor C}. +Set Universe Checking. + +(* source functor. *) +Unset Universe Checking. +#[wrapper] + HB.mixin Record SPreFunctor_IsFunctor T of SPreFunctor T := { + is_sfunctor : PreFunctor_IsFunctor (D1obj T) T (@HSource T) }. +HB.structure Definition SFunctor : Set := {C of SPreFunctor_IsFunctor C}. +Set Universe Checking. + +(* target functor. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record TPreFunctor_IsFunctor T of TPreFunctor T := { + is_tfunctor : PreFunctor_IsFunctor (D1obj T) T (@HTarget T) }. +HB.structure Definition TFunctor : Set := {C of TPreFunctor_IsFunctor C}. +Set Universe Checking. + + +(** Unit functor *) + +(* unit prefunctor. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsUPreFunctor T of HDQuiver T & TFunctor T := + { is_uprefunctor : IsPreFunctor T (D1obj T) (@H1Unit T) }. +HB.structure Definition UPreFunctor : Set := {C of IsUPreFunctor C}. +Set Universe Checking. + +(* unit functor. *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record UPreFunctor_IsFunctor T of UPreFunctor T := { + is_ufunctor : PreFunctor_IsFunctor T (D1obj T) (@H1Unit T) }. +HB.structure Definition UFunctor : Set := {C of UPreFunctor_IsFunctor C}. +Set Universe Checking. + +Unset Universe Checking. +(* HB.about Functor. *) +HB.structure Definition STUFunctor : Set := + {C of SFunctor C & TFunctor C & UFunctor C}. +Set Universe Checking. + + +(** Lifting of Source, Target and Unit functors to D1 morphisms *) + +(* 2-cell source *) +Definition H1Source (T: SFunctor.type) (a b: @D1obj T) + (m: @d1hom T a b) : + (HSource a) ~> (HSource b) := (@HSource T) <$> m. + +(* 2-cell target *) +Definition H1Target (T: TFunctor.type) (a b: @D1obj T) + (m: @d1hom T a b) : + (HTarget a) ~> (HTarget b) := (@HTarget T) <$> m. + +(* horizontal 2-cell unit (maps vertical morphisms to horizontally + unitary 2-cells) *) +Definition H2Unit (T: UFunctor.type) (a b: T) (m: @hom T a b) : + (H1Unit a) ~> (H1Unit b) := (@H1Unit T) <$> m. + +(* DP objects source and target *) +Lemma DPsource (T: STUFunctor.type) (a: DPobj T) : + HSource (H1Comp a) = HSource (TT2 (h_first a)). + destruct a; simpl in *; simpl. + auto. +Defined. + +Lemma DPtarget (T: STUFunctor.type) (a: DPobj T) : + HTarget (H1Comp a) = HTarget (TT2 (h_second a)). + destruct a; simpl in *; simpl. + auto. +Defined. + + +(** Horizontal product category (D1 *d0 D1) *) +(* DPobj T is the pseudo-pullback category used to deal with + products of D1 (where the adjacency condition is expressed + w.r.t. D0 *) + +(* horizontal composition of two (naked) horizontal morphisms *) +Definition l_hcomp (T: UFunctor.type) (a0 a1 a2: T) + (h0: hhom a0 a1) (h1: hhom a1 a2) : D1obj T := + @TT2 T _ a0 a2 (hcomp a0 a1 a2 h0 h1). + +(* +Notation "'sigma' x .. y , p" := + (sigT (fun x => .. (sigT (fun y => p)) ..)) + (at level 200, x binder, right associativity, + format "'[' 'sigma' '/ ' x .. y , '/ ' p ']'") + : type_scope. +*) + +(** DPobj quiver *) +Definition DP_hom (T: STUFunctor.type) (x y: DPobj T) := + sigma (hh0: D1hom (h_first x) (h_first y)) + (hh1: D1hom (h_second x) (h_second y)), + H1Target hh0 = H1Source hh1. + +HB.instance Definition DPQuiver (T: STUFunctor.type) : + IsQuiver (DPobj T) := + IsQuiver.Build (DPobj T) (fun A B => @DP_hom T A B). + + +(** Product precategory *) + +Lemma DP_id_eq (T : STUFunctor.type) (a: DPobj T) : + H1Target (@idmap (@D1obj T) (H2First a)) = + H1Source (@idmap (@D1obj T) (H2Second a)). +unfold H1Target, HTarget. +unfold H1Source, HSource. +repeat rewrite F1; auto. +Defined. + +(* DPobj identity *) +Definition DP_id (T: STUFunctor.type) (A: DPobj T) : A ~> A := + let h0 := h_first A + in let h1 := h_second A + in let uu0 := @idmap (D1obj T) (TT2 h0) + in let uu1 := @idmap (D1obj T) (TT2 h1) + in @existT (D1hom h0 h0) + (fun hh0: (D1hom h0 h0) => + sigma (hh1 : D1hom h1 h1), H1Target hh0 = H1Source hh1) uu0 + (@existT (D1hom h1 h1) + (fun hh1: (D1hom h1 h1) => H1Target uu0 = H1Source hh1) uu1 + (@DP_id_eq T A)). + +Definition DP_comp_auxA (T : STUFunctor.type) + (A B C : DPobj T) + (hhA0 : D1hom (h_first A) (h_first B)) + (hhA1 : D1hom (h_second A) (h_second B)) + (ppA : H1Target hhA0 = H1Source hhA1) + (hhB0 : D1hom (h_first B) (h_first C)) + (hhB1 : D1hom (h_second B) (h_second C)) + (ppB : H1Target hhB0 = H1Source hhB1) : + (H1Target hhA0) \; (H1Target hhB0) = + (H1Source hhA1) \; (H1Source hhB1). + rewrite ppA. + rewrite ppB. + reflexivity. +Defined. + +Definition DP_comp_auxS (T : STUFunctor.type) + (A B C : DPobj T) + (hhA0 : D1hom (h_first A) (h_first B)) + (hhA1 : D1hom (h_second A) (h_second B)) + (ppA : H1Target hhA0 = H1Source hhA1) + (hhB0 : D1hom (h_first B) (h_first C)) + (hhB1 : D1hom (h_second B) (h_second C)) + (ppB : H1Target hhB0 = H1Source hhB1) : + H1Source (hhA1 \; hhB1) = (H1Source hhA1) \; (H1Source hhB1). + unfold H1Source, HSource. + repeat rewrite Fcomp. + reflexivity. +Defined. + +Definition DP_comp_auxT (T : STUFunctor.type) + (A B C : DPobj T) + (hhA0 : D1hom (h_first A) (h_first B)) + (hhA1 : D1hom (h_second A) (h_second B)) + (ppA : H1Target hhA0 = H1Source hhA1) + (hhB0 : D1hom (h_first B) (h_first C)) + (hhB1 : D1hom (h_second B) (h_second C)) + (ppB : H1Target hhB0 = H1Source hhB1) : + H1Target (hhA0 \; hhB0) = (H1Target hhA0) \; (H1Target hhB0). + unfold H1Target, HTarget. + repeat rewrite Fcomp. + reflexivity. +Defined. + +Definition DP_comp_auxI (T : STUFunctor.type) + (A B C : DPobj T) + (hhA0 : D1hom (h_first A) (h_first B)) + (hhA1 : D1hom (h_second A) (h_second B)) + (ppA : H1Target hhA0 = H1Source hhA1) + (hhB0 : D1hom (h_first B) (h_first C)) + (hhB1 : D1hom (h_second B) (h_second C)) + (ppB : H1Target hhB0 = H1Source hhB1) : + A ~> C. + econstructor 1 with (comp hhA0 hhB0). + econstructor 1 with (comp hhA1 hhB1). + setoid_rewrite DP_comp_auxS; eauto. + setoid_rewrite DP_comp_auxT; eauto. + eapply DP_comp_auxA; eauto. +Defined. + +(* DPobj composition, defined in proof mode *) +Definition DP_comp (T: STUFunctor.type) (A B C: DPobj T) : + (A ~> B) -> (B ~> C) -> A ~> C. + intros chA chB. + destruct chA as [hhA0 [hhA1 ppA]]. + destruct chB as [hhB0 [hhB1 ppB]]. + eapply DP_comp_auxI; eauto. +Defined. + +(* DPobj is a precategory *) +HB.instance Definition DPPreCat (T: STUFunctor.type) : + Quiver_IsPreCat (DPobj T) := + Quiver_IsPreCat.Build (DPobj T) (@DP_id T) (@DP_comp T). + +(* + have HcompP : + (a b : DPobj T) + (f g : a ~> b), + proj1T f = proj1t f -> + + -> + f = g. + + exists a b p, + fst f = a + f = (a,b,p) +*) + +(** Product category *) + +Lemma DP_LeftUnit_lemma (T : STUFunctor.type) : + forall (a b : DPobj T) (f : a ~> b), idmap \; f = f. + + move => a b [x [x0 e]] /=. + simpl in *. + unfold idmap; simpl. + unfold DP_id; simpl. + unfold comp; simpl. + unfold DP_comp_auxI; simpl. + + assert (idmap \; x = x) as A. + { rewrite comp1o; auto. } + + assert (idmap \; x0 = x0) as A0. + { rewrite comp1o; auto. } + + assert (H1Target (idmap \; x) = H1Source (idmap \; x0)) as B. + { rewrite A. + rewrite A0; auto. } + + destruct a eqn: aaa. + destruct b eqn: bbb. + simpl. + + assert (existT + (fun hh0 : D1hom h_first0 h_first1 => + sigma hh1 : D1hom h_second0 h_second1,H1Target hh0 = H1Source hh1) + (idmap \; x) + (existT + (fun hh1 : D1hom h_second0 h_second1 => + H1Target (idmap \; x) = H1Source hh1) + (idmap \; x0) + B) = + existT + (fun hh0 : D1hom h_first0 h_first1 => + sigma hh1 : D1hom h_second0 h_second1,H1Target hh0 = H1Source hh1) + x + (existT + (fun hh1 : D1hom h_second0 h_second1 => H1Target x = H1Source hh1) + x0 + e)) as C. + { revert B. + revert A. + revert A0. + generalize (idmap \; x) as v. + generalize (idmap \; x0) as v0. + intros v0 v A0. + rewrite A0. + intro A. + rewrite A. + intro B. + + assert (B = e) as BE. + { eapply Prop_irrelevance. } + + rewrite BE. + reflexivity. +} + + inversion aaa; subst. + rewrite [Morphisms.trans_sym_co_inv_impl_morphism _ _ _ _ _] + (Prop_irrelevance _ B). + eapply C. +Qed. + +Lemma DP_RightUnit_lemma (T : STUFunctor.type) : + forall (a b : DPobj T) (f : a ~> b), f \; idmap = f. + + move => a b [x [x0 e]] /=. + simpl in *. + unfold idmap; simpl. + unfold DP_id; simpl. + unfold comp; simpl. + unfold DP_comp_auxI; simpl. + + assert (x \; idmap = x) as A. + { rewrite compo1; auto. } + + assert (x0 \; idmap = x0) as A0. + { rewrite compo1; auto. } + + assert (H1Target (x \; idmap) = H1Source (x0 \; idmap)) as B. + { rewrite A. + rewrite A0; auto. } + + destruct a eqn: aaa. + destruct b eqn: bbb. + simpl. + + assert (existT + (fun hh0 : D1hom h_first0 h_first1 => + sigma hh1 : D1hom h_second0 h_second1, + H1Target hh0 = H1Source hh1) + (x \; idmap) + (existT + (fun hh1 : D1hom h_second0 h_second1 => + H1Target (x \; idmap) = H1Source hh1) + (x0 \; idmap) + B) = + existT + (fun hh0 : D1hom h_first0 h_first1 => + sigma hh1 : D1hom h_second0 h_second1, + H1Target hh0 = H1Source hh1) + x + (existT + (fun hh1 : D1hom h_second0 h_second1 => + H1Target x = H1Source hh1) + x0 + e)) as C. + { revert B. + revert A. + revert A0. + generalize (x \; idmap) as v. + generalize (x0 \; idmap) as v0. + intros v0 v A0. + rewrite A0. + intro A. + rewrite A. + intro B. + + assert (B = e) as BE. + { eapply Prop_irrelevance. } + + rewrite BE. + reflexivity. + } + + inversion aaa; subst. + rewrite [Morphisms.trans_sym_co_inv_impl_morphism _ _ _ _ _] + (Prop_irrelevance _ B). + eapply C. +Qed. + +Lemma DP_Assoc_lemma (T : STUFunctor.type) : + forall (a b c d : DPobj T) (f : a ~> b) (g : b ~> c) (h : c ~> d), + f \; g \; h = (f \; g) \; h. + intros. + remember f as f1. + remember g as g1. + remember h as h1. + destruct f as [x0 s0]. + destruct g as [x1 s1]. + destruct h as [x2 s2]. + destruct s0 as [y0 e0]. + destruct s1 as [y1 e1]. + destruct s2 as [y2 e2]. + simpl. + + set (x01 := comp x0 x1). + set (x12 := comp x1 x2). + set (x0_12 := comp x0 x12). + set (x01_2 := comp x01 x2). + set (y01 := comp y0 y1). + set (y12 := comp y1 y2). + set (y0_12 := comp y0 y12). + set (y01_2 := comp y01 y2). + + assert (x0_12 = x01_2) as X0. + { subst x0_12 x01_2. + rewrite compoA; eauto. } + assert (y0_12 = y01_2) as Y0. + { subst y0_12 y01_2. + rewrite compoA; eauto. } + + set (x01_t := comp (H1Target x0) (H1Target x1)). + set (x01_2_t := comp x01_t (H1Target x2)). + set (x12_t := comp (H1Target x1) (H1Target x2)). + set (x0_12_t := comp (H1Target x0) x12_t). + set (y01_s := comp (H1Source y0) (H1Source y1)). + set (y01_2_s := comp y01_s (H1Source y2)). + set (y12_s := comp (H1Source y1) (H1Source y2)). + set (y0_12_s := comp (H1Source y0) y12_s). + + assert (x01_t = y01_s) as E01. + { subst x01_t y01_s. + rewrite e0. + rewrite e1; auto. } + assert (x01_2_t = y01_2_s) as E01_2. + { subst x01_2_t y01_2_s. + rewrite E01. + rewrite e2; auto. } + assert (x12_t = y12_s) as E12. + { subst x12_t y12_s. + rewrite e1. + rewrite e2; auto. } + assert (x0_12_t = y0_12_s) as E0_12. + { subst x0_12_t y0_12_s. + rewrite E12. + rewrite e0; auto. } + + assert (x0_12_t = x01_2_t) as E02T. + { subst x0_12_t x01_2_t. + subst x12_t x01_t. + rewrite compoA; auto. } + assert (y0_12_s = y01_2_s) as E02S. + { subst y0_12_s y01_2_s. + subst y12_s y01_s. + rewrite compoA; auto. } + + unfold comp. + simpl. + unfold DP_comp. + simpl. + inversion Heqf1; subst. + clear H. + + unfold DP_comp_auxI; simpl. + + assert (H1Target (x0 \; x1 \; x2) = + H1Source (y0 \; y1 \; y2)) as KR. + { subst x0_12_t y0_12_s. + subst x12_t y12_s. + unfold H1Target. + repeat rewrite Fcomp; simpl. + unfold H1Target in E0_12. + rewrite E0_12. + unfold H1Source. + repeat rewrite Fcomp; simpl. + auto. + } + + assert (H1Target ((x0 \; x1) \; x2) = + H1Source ((y0 \; y1) \; y2)) as KL. + { subst x01_2_t y01_2_s. + subst x01_t y01_s. + unfold H1Target. + repeat rewrite Fcomp; simpl. + unfold H1Target in E01_2. + rewrite E01_2. + unfold H1Source. + repeat rewrite Fcomp; simpl. + auto. + } + + assert (existT + (fun hh0 : D1hom (h_first a) (h_first d) => + sigma hh1 : D1hom (h_second a) (h_second d), + H1Target hh0 = H1Source hh1) + (x0 \; x1 \; x2) + (existT + (fun hh1 : D1hom (h_second a) (h_second d) => + H1Target (x0 \; x1 \; x2) = H1Source hh1) + (y0 \; y1 \; y2) + KR) + = + existT + (fun hh0 : D1hom (h_first a) (h_first d) => + sigma hh1 : D1hom (h_second a) (h_second d), + H1Target hh0 = H1Source hh1) + ((x0 \; x1) \; x2) + (existT + (fun hh1 : D1hom (h_second a) (h_second d) => + H1Target ((x0 \; x1) \; x2) = H1Source hh1) + ((y0 \; y1) \; y2) + KL)) as KA. + { revert KL. + revert KR. + subst x0_12 x01_2 x12 x01. + subst y0_12 y01_2 y12 y01. + rewrite <- X0. + rewrite <- Y0. + intros KR KL. + + assert (KR = KL) as I1. + { eapply Prop_irrelevance. } + rewrite I1. + reflexivity. + } + + rewrite [Morphisms.trans_sym_co_inv_impl_morphism _ _ _ _ _] + (Prop_irrelevance _ KR). + + rewrite [Morphisms.trans_sym_co_inv_impl_morphism _ _ _ _ _] + (Prop_irrelevance _ KL). + eapply KA. +Qed. + +Program Definition DPCatP (T: STUFunctor.type) : + PreCat_IsCat (DPobj T). +econstructor. +eapply DP_LeftUnit_lemma; eauto. +eapply DP_RightUnit_lemma; eauto. +eapply DP_Assoc_lemma; eauto. +Qed. + +(* DPobj is a category *) +HB.instance Definition DPCat (T: STUFunctor.type) := DPCatP T. + + +(** Horizontal composition functor and strict double categories *) + +(* fst horizontal projection prefunctor *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsHFPreFunctor T of STUFunctor T := + { is_hfprefunctor : IsPreFunctor (DPobj T) (D1obj T) (@H2First T) }. +HB.structure Definition HFPreFunctor : Set := {C of IsHFPreFunctor C}. +Set Universe Checking. + +(* fst horizontal projection functor *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record HFPreFunctor_IsFunctor T of HFPreFunctor T := { + is_hffunctor : PreFunctor_IsFunctor (DPobj T) (D1obj T) (@H2First T) }. +HB.structure Definition HFFunctor : Set := {C of HFPreFunctor_IsFunctor C}. +Set Universe Checking. + +(* snd horizontal projection prefunctor *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsHSPreFunctor T of STUFunctor T := + { is_hsprefunctor : IsPreFunctor (DPobj T) (D1obj T) (@H2Second T) }. +HB.structure Definition HSPreFunctor : Set := {C of IsHSPreFunctor C}. +Set Universe Checking. + +(* snd horizontal projection functor *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record HSPreFunctor_IsFunctor T of HSPreFunctor T := { + is_hsfunctor : PreFunctor_IsFunctor (DPobj T) (D1obj T) (@H2Second T) }. +HB.structure Definition HSFunctor : Set := {C of HSPreFunctor_IsFunctor C}. +Set Universe Checking. + +(* composition prefunctor *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record IsCPreFunctor T of STUFunctor T := + { is_cprefunctor : IsPreFunctor (DPobj T) (D1obj T) (@H1Comp T) }. +HB.structure Definition CPreFunctor : Set := {C of IsCPreFunctor C}. +Set Universe Checking. + +(* composition functor - gives the definition of Strict Double Category *) +Unset Universe Checking. +#[wrapper] +HB.mixin Record CPreFunctor_IsFunctor T of CPreFunctor T := { + is_cfunctor : PreFunctor_IsFunctor (DPobj T) (D1obj T) (@H1Comp T) }. +(* #[short(type="sdoublecat")] *) +HB.structure Definition CFunctor : Set := {C of CPreFunctor_IsFunctor C}. +Set Universe Checking. + +(* All functors together *) +Unset Universe Checking. +HB.structure Definition FCFunctor : Set := + {C of HFFunctor C & HSFunctor C & CFunctor C}. +Set Universe Checking. + + +(* first and second projection from pairs of cells *) +Definition HH2First (T: HFFunctor.type) (a b: DPobj T) + (m: DP_hom a b) : H2First a ~> H2First b := (@H2First T) <$> m. + +Definition HH2Second (T: HSFunctor.type) (a b: DPobj T) + (m: DP_hom a b) : H2Second a ~> H2Second b := (@H2Second T) <$> m. + + +(* horizontal 2-cell composition: maps two adjecent pairs of + horizontal morphisms (a and b) and a pullback-category morphism + between them (m, which basically gives two adjecent cells) to a + 2-cell morphism between the horizontal composition (HComp) of each + pair *) +Definition HC2Comp (T: CFunctor.type) (a b: DPobj T) + (m: DP_hom a b) : + d1hom (H1Comp a) (H1Comp b) := @Fhom _ _ (@H1Comp T) a b m. + +(* +Definition HC2Comp (T: CFunctor.type) (a b: DPobj T) + (m: @hom (DPobj T) a b) : + d1hom (H1Comp a) (H1Comp b) := @Fhom _ _ (@H1Comp T) a b m. +*) + +Program Definition HC2Comp_flat (T: CFunctor.type) (a0 a1 a2 b0 b1 b2: T) + (h0: hhom a0 a1) (h1: hhom a1 a2) + (k0: hhom b0 b1) (k1: hhom b1 b2) + (hh0: D1hom h0 k0) + (hh1: D1hom h1 k1) + (k: H1Target hh0 = H1Source hh1) : + D1hom (hcomp _ _ _ h0 h1) (hcomp _ _ _ k0 k1) := + (* d1hom (l_hcomp h0 h1) (l_hcomp k0 k1) := *) + @Fhom _ _ (@H1Comp T) (GC h0 h1) (GC k0 k1) _. +Obligation 1. +refine (@existT (D1hom h0 k0) _ hh0 (@existT (D1hom h1 k1) _ hh1 k)). +Show Proof. + +Defined. + + +(* quasi-double category *) +Unset Universe Checking. +HB.mixin Record IsQDoubleCat T of FCFunctor T := { + unit_source : forall (a b: T) (m: hom a b), + H1Source (H2Unit m) = m ; + + unit_target : forall (a b: T) (m: hom a b), + H1Target (H2Unit m) = m ; +}. +#[short(type="qdoublecat")] +HB.structure Definition QDoubleCat : Set := + { C of IsQDoubleCat C }. +Set Universe Checking. + + +(* definition of strict double precategory *) +Unset Universe Checking. +HB.mixin Record IsPreSDoubleCat T of QDoubleCat T := { + source_comp_dist : forall (a b: DPobj T) (m: DP_hom a b), + TT2 (H1Source (HC2Comp m)) = TT2 (H1Source (HH2First m)) ; + + target_comp_dist : forall (a b: DPobj T) (m: DP_hom a b), + TT2 (H1Target (HC2Comp m)) = TT2 (H1Target (HH2Second m)) ; +}. +#[short(type="presdoublecat")] +HB.structure Definition PreSDoubleCat : Set := + { C of IsPreSDoubleCat C }. +Set Universe Checking. + + +(* alternative definition of strict double precategory *) +Unset Universe Checking. +HB.mixin Record IsPreSDoubleCat1 T of QDoubleCat T := { + source_comp_dist1 : forall (a0 a1 a2 b0 b1 b2: T) + (h0: hhom a0 a1) (h1: hhom a1 a2) + (k0: hhom b0 b1) (k1: hhom b1 b2) + (hh0: D1hom h0 k0) + (hh1: D1hom h1 k1) + (K: H1Target hh0 = H1Source hh1), + H1Source (HC2Comp_flat K) = H1Source hh0 ; + + target_comp_dist1 : forall (a0 a1 a2 b0 b1 b2: T) + (h0: hhom a0 a1) (h1: hhom a1 a2) + (k0: hhom b0 b1) (k1: hhom b1 b2) + (hh0: D1hom h0 k0) + (hh1: D1hom h1 k1) + (K: H1Target hh0 = H1Source hh1), + H1Target (HC2Comp_flat K) = H1Target hh1 ; +}. +#[short(type="presdoublecat1")] +HB.structure Definition PreSDoubleCat1 : Set := + { C of IsPreSDoubleCat1 C }. +Set Universe Checking. + + + +(** Horizontal 2-cell level category (H1 category) *) + +HB.tag Definition H1obj (C: VHQuiver.type) := Total2 (@hom C). + +(* a and b are vertical (D0) morphisms. Gives the condition for a +horizontal (H1) morphism between them. Given two horizontal (H0) +morphisms h1 and h2 between sources and targets of the vertical ones, +respectively, we expect that there is a vertical (D1) morphism between +them. *) +Definition H1hom (T: STUFunctor.type) (a b: H1obj T) := + sigma (h1: hhom (source a) (source b)) (h2: hhom (target a) (target b)) + (hh: D1hom h1 h2), + H1Source hh = this_morph a /\ H1Target hh = this_morph b. +(* +Definition H1hom (T: DQuiver.type) (a b: H1obj T) := + sigma (h1: hhom (source a) (source b)) (h2: hhom (target a) (target b)), + @hom (D1obj T) (TT2 h1) (TT2 h2). +*) + +HB.instance Definition H1Quiver (T: STUFunctor.type) : + IsQuiver (H1obj T) := + IsQuiver.Build (H1obj T) (@H1hom T). + + +Program Definition H1_id (T: QDoubleCat.type) (a: H1obj T) : a ~> a. +unfold hom. +simpl. +unfold H1hom. +destruct a. +simpl; simpl in *. +econstructor 1 with (x:= hunit source0). +econstructor 1 with (x:= hunit target0). +econstructor 1 with (x:= H2Unit this_morph0). +split. +eapply unit_source. +eapply unit_target. +Defined. + +Program Definition H1_comp (T: PreSDoubleCat1.type) (a b c: H1obj T) + (hh1: a ~> b) (hh2: b ~> c) : a ~> c. +destruct a. +destruct b. +destruct c. +unfold hom in *; simpl in *. +unfold H1hom in *; simpl in *. +destruct hh1 as [h1 [k1 [hk1 [hk1S hk1T]]]]. +destruct hh2 as [h2 [k2 [hk2 [hk2S hk2T]]]]. +econstructor 1 with (x:= hcomp _ _ _ h1 h2). +econstructor 1 with (x:= hcomp _ _ _ k1 k2). +assert (@H1Target T (TT2 h1) (TT2 k1) hk1 = + @H1Source T (TT2 h2) (TT2 k2) hk2) as K. +{ + rewrite hk1T. + rewrite hk2S; auto. +} + +econstructor 1 with (x := HC2Comp_flat K). + +split. +rewrite source_comp_dist1; auto. +rewrite target_comp_dist1; auto. +Defined. + +HB.instance Definition H1PreCat (T: PreSDoubleCat1.type) : + IsPreCat (H1obj T) := + IsPreCat.Build (H1obj T) (@H1_id T) (@H1_comp T). + +Unset Universe Checking. +#[wrapper] +(* Fail HB.mixin Record IsSDoubleCat T of PreSDoubleCat1 T := { + Fail HB.mixin Record IsSDoubleCat T of IsPreSDoubleCat1 T := { *) +HB.mixin Record IsSDoubleCat (T: PreSDoubleCat1.type) := { + is_sdcat : PreCat_IsCat (H1obj T) }. +#[short(type="sdcat")] +HB.structure Definition SDoubleCat : Set := + { C of IsSDoubleCat C }. +Set Universe Checking. + + + +(* +Program Definition H2hom (T: DQuiver.type) (a b: H1obj T) := + match (a, b) with + | (@TT2 _ _ sa ta ma, @TT2 _ _ sb tb mb) => + sigma (h1: hhom sa sb) (h2: hhom ta tb), (@TT2 T _ h1) ~> (TT2 h2) end. + +(* Precategory based on the DQuiver (i.e. precategory D1). Gives: + vertical 2-cell identity morphism. + vertical 2-cell composition. *) +HB.instance Definition H2Quiver (T: DQuiver.type) : + IsQuiver (transpose (D1obj T)) := + IsQuiver.Build (transpose (D1obj T)) + + + +Unset Universe Checking. +#[wrapper] +HB.mixin Record _IsD1PreCat T of DQuiver T := { + is_d1precat : Quiver_IsPreCat (@D1obj T) }. +#[short(type="d1precat")] +HB.structure Definition D1PreCat : Set := + { C of Quiver_IsPreCat (@D1obj C) }. +Set Universe Checking. + + +(* Like requiring HCat T *) +HB.mixin Record IsDCat T of CFunctor T := { + h1_left_unital : forall (a0 a1: T) (h : hhom a0 a1), + @hcomp T a0 a0 a1 (hunit a0) h = h ; + + h1_right_unital : forall (a0 a1: T) (h : hhom a0 a1), + @hcomp T a0 a1 a1 h (hunit a1) = h ; + + h1_assoc : forall (a0 a1 a2 a3: T) + (h1 : hhom a0 a1) + (h2: hhom a1 a2) (h3: hhom a2 a3), + @hcomp T a0 a2 a3 (@hcomp T a0 a1 a2 h1 h2) h3 = + @hcomp T a0 a1 a3 h1 (@hcomp T a1 a2 a3 h2 h3) +}. +Unset Universe Checking. +#[short(type="sdoublecat")] +HB.structure Definition SDoubleCat : Set := { C of IsDCat C }. +Set Universe Checking. + +Lemma DP1source (T: CFunctor.type) (a b: DPobj T) + (m: DP_hom a b) : + H1Source (HC2Comp m) = H1Source (HC2Comp m) /\ + H1Source (projT1 m) = H1Source (projT1 m). + remember m as m1. + destruct m1. + simpl. + destruct s. + unfold HC2Comp. + unfold H1Comp. + unfold hhcomp. + + unfold Fhom. + simpl. + unfold H1Source. + unfold HSource. + unfold hhom. + simpl. + destruct a. + destruct b. + unfold hhom in *. + simpl; simpl in *. + unfold DP_hom in m. + simpl in *. + +Lemma DP1source (T: CFunctor.type) (a b: DPobj T) + (m: @hom (DPobj T) a b) : + H1Source (HC2Comp m) = + H1Source (TT2 (h_first m)). + destruct a; simpl in *; simpl. + auto. +Defined. + + +Lemma Adj12_3 (T: CFunctor.type) (a b: DPobj T) + (m: @hom (DPobj T) a b) : + H1Source (HC2Comp m) = H1Source (projT1 a). + + + + T: CFunctor.type} {a0 a1 a2 a3 b0 b1 b2 b3: T} + {h1: hhom a0 a1} {h2: hhom a1 a2} {h3: hhom a2 a3} + {k1: hhom b0 b1} {k2: hhom b1 b2} {k3: hhom b2 b3} + (hh1: D1hom h1 k1) (hh2: D1hom h2 k2) (hh3: D1hom h3 k3) + (A1: H1Target hh1 = H1Source hh2) + (A2: H1Target hh2 = H1Source hh3) : + let hh12 := @HC2Comp_flat T a0 a1 a2 b0 b1 b2 h1 h2 k1 k2 hh1 hh2 A1 + in H1Target hh12 = H1Source hh3. + + + + +Lemma Adj12_3 {T: CFunctor.type} {a0 a1 a2 a3 b0 b1 b2 b3: T} + {h1: hhom a0 a1} {h2: hhom a1 a2} {h3: hhom a2 a3} + {k1: hhom b0 b1} {k2: hhom b1 b2} {k3: hhom b2 b3} + (hh1: D1hom h1 k1) (hh2: D1hom h2 k2) (hh3: D1hom h3 k3) + (A1: H1Target hh1 = H1Source hh2) + (A2: H1Target hh2 = H1Source hh3) : + let hh12 := @HC2Comp_flat T a0 a1 a2 b0 b1 b2 h1 h2 k1 k2 hh1 hh2 A1 + in H1Target hh12 = H1Source hh3. + simpl. + rewrite - A2. + clear A2 hh3. + clear h3 k3. + unfold HC2Comp_flat. + unfold H1Comp. + + unfold H1Target, H1Source in *. + unfold HTarget, HSource in *. + unfold target. + unfold HC2Comp_flat_obligation_1; simpl. + unfold H1Comp; simpl. + unfold hhcomp; simpl. + + unfold Fhom in * ; simpl. + unfold IsPreFunctor.Fhom in *. + simpl; simpl in *. + unfold D1hom in *. + unfold d1hom in *; simpl in *. + unfold hhom in *. + unfold hom in *. + simpl in *. + + unfold l_hcomp. + unfold hcomp. + simpl. + + + unfold D1hom in *. + simpl. + unfold H1Target, H1Source in A1. + unfold HTarget, HSource in A1. + simpl in *. + unfold Fhom in A1. + + assert (forall U, U <$> + (IsPreFunctor.Fhom (Op_isMx__306__ELIM T) + (existT + (fun hh0 : D1hom h1 k1 => + sigma hh3 : D1hom h2 k2, H1Target hh0 = H1Source hh3) hh1 + (existT (fun hh0 : D1hom h2 k2 => H1Target hh1 = H1Source hh0) hh2 + A1))) = + U <$> hh2). + + rewrite - A2. + unfold H1Target, H1Source. + unfold HTarget, HSource. + unfold D1hom in *. + unfold d1hom in *. + unfold hom. + simpl. + unfold Fhom. + simpl. +Admitted. + +Lemma Adj1_23 {T: CFunctor.type} {a0 a1 a2 a3 b0 b1 b2 b3: T} + {h1: hhom a0 a1} {h2: hhom a1 a2} {h3: hhom a2 a3} + {k1: hhom b0 b1} {k2: hhom b1 b2} {k3: hhom b2 b3} + (hh1: D1hom h1 k1) (hh2: D1hom h2 k2) (hh3: D1hom h3 k3) + (A1: H1Target hh1 = H1Source hh2) + (A2: H1Target hh2 = H1Source hh3) : + let hh23 := @HC2Comp_flat T a1 a2 a3 b1 b2 b3 h2 h3 k2 k3 hh2 hh3 A2 + in H1Target hh1 = H1Source hh23. +Admitted. + +HB.mixin Record IsDCat2 T of CFunctor T := { + h2_left_unital : forall (a0 a1 b0 b1: T) (m: @hom T a0 b0) + (h1: hhom a0 a1) (k1: hhom b0 b1) + (hh1: D1hom h1 k1) + (A: H1Target (@H2Unit T a0 b0 m) = H1Source hh1), + TT2 (@HC2Comp_flat T a0 a0 a1 b0 b0 b1 (hunit a0) h1 (hunit b0) k1 + (@H2Unit T a0 b0 m) hh1 A) = TT2 hh1 ; + + h2_right_unital : forall (a0 a1 b0 b1: T) (m: @hom T a1 b1) + (h1: hhom a0 a1) (k1: hhom b0 b1) + (hh1: D1hom h1 k1) + (A: H1Target hh1 = H1Source (@H2Unit T a1 b1 m)), + TT2 (@HC2Comp_flat T a0 a1 a1 b0 b1 b1 h1 (hunit a1) k1 (hunit b1) + hh1 (@H2Unit T a1 b1 m) A) = TT2 hh1 ; + + h2_assoc : forall (a0 a1 a2 a3 b0 b1 b2 b3: T) + (h1: hhom a0 a1) (h2: hhom a1 a2) (h3: hhom a2 a3) + (k1: hhom b0 b1) (k2: hhom b1 b2) (k3: hhom b2 b3) + (hh1: D1hom h1 k1) (hh2: D1hom h2 k2) (hh3: D1hom h3 k3) + (A1: H1Target hh1 = H1Source hh2) + (A2: H1Target hh2 = H1Source hh3), + let hh12 := + @HC2Comp_flat T a0 a1 a2 b0 b1 b2 h1 h2 k1 k2 hh1 hh2 A1 + in let hh23 := + @HC2Comp_flat T a1 a2 a3 b1 b2 b3 h2 h3 k2 k3 hh2 hh3 A2 + in TT2 (HC2Comp_flat (Adj12_3 A1 A2)) = + TT2 (HC2Comp_flat (Adj1_23 A1 A2)) ; +}. +Unset Universe Checking. +#[short(type="sdoublecat2")] +HB.structure Definition SDoubleCat2 : Set := { C of IsDCat2 C }. +Set Universe Checking. + + +(* hcomp (hm, hu) = prj1 (hm, hu) = hm + hcomp (hu, hm) = prj2 (hu, hm) = hm + (hm1 * hm2) * hm3 ~> hm1 * (hm2 * hm3) + +(* Double category with universal characterization of weak + horizontal associativity *) +HB.mixin Record IsDCat_UA T of CFunctor T := { + associator : forall (a0 a1 a2 a3: T) + (h1: @hhom T a0 a1) (h2: @hhom T a1 a2) + (h3: @hhom T a2 a3), + let h23 := hcomp a1 a2 a3 h2 h3 in + let h12 := hcomp a0 a1 a2 h1 h2 in + let hh1 := hcomp a0 a1 a3 h1 h23 in + let hh2 := hcomp a0 a2 a3 h12 h3 in + @hom (HHomSet T) (@HO T (@hhom T) a0 a3 hh2) + (@HO T (@hhom T) a0 a3 hh1) +}. +*) + +Definition l_hcomp (T: SDCat.type) (a0 a1 a2: T) + (h0: hhom a0 a1) (h1: hhom a1 a2) : D1obj T := + @TT2 T _ a0 a2 (h0 \; h1). +*) diff --git a/theories/encatI.v b/theories/encatI.v new file mode 100644 index 000000000..228ace8fd --- /dev/null +++ b/theories/encatI.v @@ -0,0 +1,1599 @@ +Require Import ssreflect ssrfun. +Unset Universe Checking. +From HB Require Import structures cat encatD. +Set Universe Checking. +Require Import Coq.Program.Equality. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. +Add Search Blacklist "__canonical__". + +Local Open Scope algebra_scope. + +Local Open Scope cat_scope. + +(* +Notation "'sigma' x .. y , p" := + (sigT (fun x => .. (sigT (fun y => p)) ..)) + (at level 200, x binder, right associativity, + format "'[' 'sigma' '/ ' x .. y , '/ ' p ']'") + : type_scope. +*) + +(************************************************************************) + +Program Definition brel_fcast {X Y C : Type} {F: X -> C} {G: Y -> C} + {a1 b1: X} {a2 b2: Y} {R: C -> C -> Type} + (e1: F a1 = G a2) (e2: F b1 = G b2) : + R (G a2) (G b2) = R (F a1) (F b1). +rewrite e1. +rewrite e2. +auto. +Defined. + +Program Definition recast2 {X Y C : Type} {F: X -> C} {G: Y -> C} + {a1 b1: X} {a2 b2: Y} {R: C -> C -> Type} + (e1: F a1 = G a2) (e2: F b1 = G b2) + (x: R (G a2) (G b2)) : R (F a1) (F b1). +rewrite -(brel_fcast e1 e2). +exact x. +Defined. + +Program Definition brel_fcast_h {X Y C : Type} {F: X -> C} {G: Y -> C} + {a1 b1: X} {a2 b2: Y} {R: C -> C -> Type} + (e1: F a1 = G a2) (e2: F b1 = G b2) + (x: R (G a2) (G b2)) (P: forall T: Type, T -> Prop) : + P _ x = P _ (recast2 e1 e2 x). +unfold recast2. +unfold eq_rect. +unfold brel_fcast. +unfold eq_ind_r. +unfold eq_ind. +unfold eq_sym. +destruct e1. +destruct e2. +auto. +Defined. + +Program Definition brel_fcast_3h {X Y C : Type} {F: X -> C} {G: Y -> C} + {a1 b1 c1: X} {a2 b2 c2: Y} {R: C -> C -> Type} + (e1: F a1 = G a2) (e2: F b1 = G b2) (e3: F c1 = G c2) + (x: R (G a2) (G b2)) (y: R (G b2) (G c2)) (z: R (G a2) (G c2)) + (P: forall T1 T2 T3: Type, T1 -> T2 -> T3 -> Prop) : + P _ _ _ x y z = P _ _ _ (recast2 e1 e2 x) (recast2 e2 e3 y) (recast2 e1 e3 z). +unfold recast2. +unfold eq_rect. +unfold brel_fcast. +unfold eq_ind_r. +unfold eq_ind. +unfold eq_sym. +destruct e1. +destruct e2. +destruct e3. +auto. +Defined. + +Program Definition brel_fcast_3hh {X Y C : Type} {F: X -> C} {G: Y -> C} + {a1 b1 c1: X} {a2 b2 c2: Y} {R: C -> C -> Type} + (e1: F a1 = G a2) (e2: F b1 = G b2) (e3: F c1 = G c2) + (x: R (G a2) (G b2)) (y: R (G b2) (G c2)) (z: R (G a2) (G c2)) + (P: forall (d1 d2 d3: C), R d1 d2 -> R d2 d3 -> R d1 d3 -> Prop) : + P _ _ _ x y z = P _ _ _ (recast2 e1 e2 x) (recast2 e2 e3 y) (recast2 e1 e3 z). +unfold recast2. +unfold eq_rect. +unfold brel_fcast. +unfold eq_ind_r. +unfold eq_ind. +unfold eq_sym. +destruct e1. +destruct e2. +destruct e3. +auto. +Defined. + +Program Definition recast2_h {X Y C : Type} {F: X -> C} {G: Y -> C} + {a1 b1: X} {a2 b2: Y} {R: C -> C -> Type} + (e1: F a1 = G a2) (e2: F b1 = G b2) + (x: R (G a2) (G b2)) (P: forall T: Type, T -> Prop) + (p: P _ x) : P _ (recast2 e1 e2 x). +rewrite -(brel_fcast_h e1 e2). +exact p. +Defined. + +Program Definition recast2_3h {X Y C : Type} {F: X -> C} {G: Y -> C} + {a1 b1 c1: X} {a2 b2 c2: Y} {R: C -> C -> Type} + (e1: F a1 = G a2) (e2: F b1 = G b2) (e3: F c1 = G c2) + (x: R (G a2) (G b2)) (y: R (G b2) (G c2)) (z: R (G a2) (G c2)) + (P: forall T1 T2 T3: Type, T1 -> T2 -> T3 -> Prop) + (p: P _ _ _ x y z) : + P _ _ _ (recast2 e1 e2 x) (recast2 e2 e3 y) (recast2 e1 e3 z). +rewrite -(brel_fcast_3h e1 e2 e3). +exact p. +Defined. + +Program Definition recast2_3hh {X Y C : Type} {F: X -> C} {G: Y -> C} + {a1 b1 c1: X} {a2 b2 c2: Y} {R: C -> C -> Type} + (e1: F a1 = G a2) (e2: F b1 = G b2) (e3: F c1 = G c2) + (x: R (G a2) (G b2)) (y: R (G b2) (G c2)) (z: R (G a2) (G c2)) + (P: forall (d1 d2 d3: C), R d1 d2 -> R d2 d3 -> R d1 d3 -> Prop) + (p: P _ _ _ x y z) : + P _ _ _ (recast2 e1 e2 x) (recast2 e2 e3 y) (recast2 e1 e3 z). +rewrite -(brel_fcast_3hh e1 e2 e3). +exact p. +Defined. + +Program Definition recast_hom {X Y C : precat} {F: X -> C} {G: Y -> C} + {a1 b1: X} {a2 b2: Y} {R: C -> C -> Type} + (e1: F a1 = G a2) (e2: F b1 = G b2) + (x: (G a2) ~> (G b2)) : (F a1) ~> (F b1). +eapply recast2; eauto. +Defined. + +Definition recast21 {X Y C : Type} {F: X -> C} {G: Y -> C} + {R: C -> C -> Type} {a b: (X * Y)} + (e: (F (fst a), F (fst b)) = (G (snd a), G (snd b))) +(* + (e1: F (fst a) = G (snd a)) (e2: F (fst b) = G (snd b)) *) + (x: R (G (snd a)) (G (snd b))) : R (F (fst a)) (F (fst b)). + destruct a as [a1 a2]. + destruct b as [b1 b2]. + inversion e; subst. + rewrite H0. + rewrite H1. + auto. +Defined. + +Definition mk_pair_eq {X Y C: Type} {F: X -> C} {G: Y -> C} {a b: (X * Y)} + (e1: F (fst a) = G (snd a)) (e2: F (fst b) = G (snd b)) : + (F (fst a), F (fst b)) = (G (snd a), G (snd b)). + destruct a as [a1 a2]. + destruct b as [b1 b2]. + simpl in *; simpl. + rewrite e1. + rewrite e2. + auto. +Defined. + + +Module commaE. + +Section homcommaE. +Context {C D E : precat} (F : C ~> E) (G : D ~> E). + +Definition ptype := { x : C * D & F x.1 = G x.2 }. + +Definition hom_psubdef (a b : ptype) := { + f : tag a ~> tag b & + (F <$> f.1) = (recast2 (tagged a) (tagged b) (G <$> f.2)) }. +#[export] +HB.instance Definition _ := IsQuiver.Build ptype hom_psubdef. +End homcommaE. + +Arguments hom_psubdef /. + +Section commaS. +Context {C D E : cat} (F : C ~> E) (G : D ~> E). +Notation ptype := (ptype F G). + +Program Definition idmap_psubdef (a : ptype) : a ~> a := @Tagged _ idmap _ _. +Next Obligation. + unfold recast2. + unfold eq_rect. + unfold brel_fcast. + unfold eq_ind_r. + unfold eq_ind. + unfold eq_sym. + destruct a. + destruct x. + simpl in *; simpl. + rewrite F1. + rewrite F1. + unfold idmap. + simpl. + destruct e. + auto. +Defined. + +Program Definition comp_psubdef (a b c : ptype) + (f : a ~> b) (g : b ~> c) : a ~> c := + @Tagged _ (tag f \; tag g) _ _. +Next Obligation. + destruct f as [ff ef]. + destruct g as [gg eg]. + destruct a as [aa ea]. + destruct aa as [a1 a2]. + destruct b as [bb eb]. + destruct bb as [b1 b2]. + destruct c as [cc ec]. + destruct cc as [c1 c2]. + destruct ff as [f1 f2]. + destruct gg as [g1 g2]. + + simpl; simpl in *. + + rewrite Fcomp. + rewrite Fcomp. + + rewrite ef. + rewrite eg. + clear ef eg. + + eapply (@recast2_3hh _ _ _ _ _ _ _ _ _ _ _ _ + ea eb ec (G <$> f2) (G <$> g2) (G <$> f2 \; G <$> g2) + (fun (d1 d2 d3: E) (x: d1 ~> d2) (y: d2 ~> d3) + (z: d1 ~> d3) => x \; y = z) ); auto. +Defined. + (* by rewrite !Fcomp -compoA (tagged g) compoA (tagged f) compoA. Qed. *) + +#[export] +HB.instance Definition _ := IsPreCat.Build ptype idmap_psubdef comp_psubdef. +Arguments idmap_psubdef /. +Arguments comp_psubdef /. + +Lemma pcomma_homeqP (a b : ptype) (f g : a ~> b) : projT1 f = projT1 g -> f = g. +Proof. +case: f g => [f fP] [g +]/= eqfg; case: _ / eqfg => gP. +by congr existT; apply: Prop_irrelevance. +Qed. + +Lemma pcomma_is_cat : PreCat_IsCat ptype. +Proof. +by split=> [[a fa] [b fb] [*]|[a fa] [b fb] [*]|*]; + apply/pcomma_homeqP; rewrite /= ?(comp1o, compo1, compoA). +Qed. + +#[export] +HB.instance Definition _ := pcomma_is_cat. + +End commaS. + +Module Exports. + HB.reexport. +End Exports. + +End commaE. + +Import commaE.Exports. + +(* +Notation "F `/` G" := (@comma.type _ _ _ F G) + (at level 40, G at level 40, format "F `/` G") : cat_scope. +Notation "a /` G" := (cst unit a `/` G) + (at level 40, G at level 40, format "a /` G") : cat_scope. +Notation "F `/ b" := (F `/` cst unit b) + (at level 40, b at level 40, format "F `/ b") : cat_scope. +Notation "a / b" := (cst unit a `/ b) : cat_scope. +*) + + +Definition pcat_prj1 {C D E F G} (P: @commaE.ptype C D E F G) : C := + fst (tag P). + +Definition pcat_prj2 {C D E F G} (P: @commaE.ptype C D E F G) : D := + snd (tag P). + +Program Definition pcat_prj1_isPreFunctor {C D E F G} := + IsPreFunctor.Build _ _ (@pcat_prj1 C D E F G) _. +Obligation 1. +About IsPreFunctor.phant_Build. +Show. +destruct H as [f Y]. +exact f.1. +Defined. + +Program Definition pcat_prj2_isPreFunctor {C D E F G} := + IsPreFunctor.Build _ _ (@pcat_prj2 C D E F G) _. +Obligation 1. +destruct H as [f Y]. +exact f.2. +Defined. + +HB.instance Definition _ {C D E F G} : IsPreFunctor _ _ pcat_prj1 := + @pcat_prj1_isPreFunctor C D E F G. + +HB.instance Definition _ {C D E F G} : IsPreFunctor _ _ pcat_prj2 := + @pcat_prj2_isPreFunctor C D E F G. + +Program Definition pcat_prj1_isFunctor {C D E: cat} {F G} := + PreFunctor_IsFunctor.Build _ _ (@pcat_prj1 C D E F G) _ _. +Obligation 2. +destruct a. +destruct b. +Show. +destruct x. +destruct f. +destruct g. +simpl; simpl in *. +unfold Fhom. +simpl. auto. +Defined. + +Program Definition pcat_prj2_isFunctor {C D E: cat} {F G} := + PreFunctor_IsFunctor.Build _ _ (@pcat_prj2 C D E F G) _ _. +Obligation 2. +destruct a. +destruct b. +destruct x. +destruct f. +destruct g. +simpl; simpl in *. +unfold Fhom. +simpl. auto. +Defined. + +HB.instance Definition _ {C D E F G} : PreFunctor_IsFunctor _ _ pcat_prj1 := + @pcat_prj1_isFunctor C D E F G. + +HB.instance Definition _ {C D E F G} : PreFunctor_IsFunctor _ _ pcat_prj2 := + @pcat_prj2_isFunctor C D E F G. + +(* +Definition pcat_prj1 {C D E F G} (P: @ptype C D E F G) : C := + fst (tag P). + +Definition pcat_prj2 {C D E F G} (P: @ptype C D E F G) : D := + snd (tag P). + +Program Definition pcat_prj1_isPreFunctor {C D E F G} := + IsPreFunctor.Build _ _ (@pcat_prj1 C D E F G) _. +Obligation 1. +destruct X as [f Y]. +exact f.1. +Defined. + +Program Definition pcat_prj2_isPreFunctor {C D E F G} := + IsPreFunctor.Build _ _ (@pcat_prj2 C D E F G) _. +Obligation 1. +destruct X as [f Y]. +exact f.2. +Defined. + +HB.instance Definition _ {C D E F G} : IsPreFunctor _ _ pcat_prj1 := + @pcat_prj1_isPreFunctor C D E F G. + +HB.instance Definition _ {C D E F G} : IsPreFunctor _ _ pcat_prj2 := + @pcat_prj2_isPreFunctor C D E F G. + +Program Definition pcat_prj1_isFunctor {C D E: cat} {F G} := + PreFunctor_IsFunctor.Build _ _ (@pcat_prj1 C D E F G) _ _. +*) + + + +(************************************************************************) + +(*** GENERALISED ENRICHED CATEGORIES *) + +Declare Scope encat_scope. +Delimit Scope encat_scope with encat. +Local Open Scope encat_scope. + +(* Enrichment in a monoidal category, following + https://ncatlab.org/nlab/show/enriched+category +*) +HB.mixin Record IsEnQuiver (V: Type) C := { + hom_object : C -> C -> V + }. +Unset Universe Checking. +HB.structure Definition EnQuiver (V: Type) : Set := + { C of IsEnQuiver V C }. +Set Universe Checking. + +(* Monoidal precategory with the enrichment operators (no axioms) *) +HB.mixin Record IsEnPreCat (V: PreMonoidal.type) C of + EnQuiver (PreMonoidal.sort V) C := { + id_element : forall (a: C), + @hom V onec (hom_object a a) ; + comp_morphism : forall (a b c: C), + @hom V (@hom_object V C b c * @hom_object V C a b) + (@hom_object V C a c) +}. +Unset Universe Checking. +HB.structure Definition EnPreCat (V: PreMonoidal.type) : Set := + { C of IsEnPreCat V C }. +Set Universe Checking. + +Notation "a ~^ b" := (hom_object a b) + (at level 99, b at level 200, format "a ~^ b") : encat_scope. +Notation "a ~^_ ( V , C ) b" := (@hom_object V C a b) + (at level 99, V at level 0, C at level 0, only parsing) : cat_scope. +Notation "~^IE a" := (id_element a) + (at level 99, format "~^IE a") : cat_scope. +Notation "~^IE_ ( V , C ) a" := (@id_element V C a) + (at level 99, V at level 0, C at level 0, only parsing) : cat_scope. +(* not working *) +Notation "~^CM a b c" := (comp_morphism a b c) + (at level 99, + format "~^CM a b c") : cat_scope. +Notation "~^CM_ ( V , C ) a b c" := (@comp_morphism V C a b c) + (at level 99, V at level 0, C at level 0, only parsing) : cat_scope. + +(* V-enriched category: + V is the monoidal category; + C is the base category that gets enriched +*) +HB.mixin Record IsEnCat (V: Monoidal.type) C of EnPreCat V C := { + ecat_comp_assoc : forall a b c d: C, + forall alpha: + (((c ~^_(V,C) d) * (b ~^_(V,C) c)) * (a ~^_(V,C) b)) ~>_V + ((c ~^_(V,C) d) * ((b ~^_(V,C) c) * (a ~^_(V,C) b))), + ((@comp_morphism V C b c d) <*> (@idmap V (a ~^_(V,C) b))) \; + (@comp_morphism V C a b d) + = + alpha \; + ((@idmap V (c ~^_(V,C) d)) <*> (@comp_morphism V C a b c)) \; + (@comp_morphism V C a c d) ; + + ecat_comp_left_unital : forall a b: C, + forall l: onec * (a ~^_(V,C) b) ~>_V (a ~^_(V,C) b), + l = ((@id_element V C b) <*> (@idmap V (a ~^_(V,C) b))) \; + (@comp_morphism V C a b b) ; + ecat_comp_right_unital : forall a b: C, + forall r: (a ~^_(V,C) b) * onec ~>_V (a ~^_(V,C) b), + r = ((@idmap V (a ~^_(V,C) b)) <*> (@id_element V C a)) \; + (@comp_morphism V C a a b) +}. +Unset Universe Checking. +#[verbose] +HB.structure Definition EnCat (V: Monoidal.type) : Set := + { C of IsEnCat V C }. +Set Universe Checking. + + +(************************************************************************) + +(*** CATEGORIES WITH PULLBACKS *) + +(* category with all prepullbacks *) +(* Ideally span is in fact expanded and the final mixin has +a pb : forall A B, cospan A B -> C +but it is not clear how to do that yet +*) +HB.mixin Record HasPBop C of Cat C := { + pbk : forall (A B: C), cospan A B -> span A B + }. +#[short(type="pbop")] +HB.structure Definition PBop := + {C of HasPBop C & PreCat C }. + +(* category with all pullbacks *) +(* Wrong: we don't wrap classes, only mixins *) +#[wrapper] +HB.mixin Record HasPreBCat C of PBop C : Type := { + is_ppbk : forall (a b : C) (c : cospan a b), + isPrePullback C a b c (@pbk C a b c) + }. +#[short(type="pbcat")] +HB.structure Definition PreBCat := + {C of HasPreBCat C}. + +#[wrapper] +HB.mixin Record HasPBCat C of PBop C & HasPreBCat C : Type := { + is_tpbk : forall (a b : C) (c : cospan a b), + prepullback_isTerminal C a b c (@pbk C a b c) + }. +#[short(type="pbcat")] +HB.structure Definition PBCat := + {C of HasPBCat C}. + + +(************************************************************************) + +(**** INTERNAL CATEGORIES *) + +(* Defining internal hom objects. + C0 and C1 are objects of C. + C0 is the object of objects, + C1 is the object of morphims (and the subject). + this will allow to define a generic _ *_C0 _ notation + by recognizing the structure of hom objects on the LHS and RHS + Basically, w.r.t. double categories, C1 represents 'horizontal' + 1-morpshisms and the D1 category, whereas C0 represents the objects + of the base D0 category. *) +HB.mixin Record isInternalHom {C: quiver} (C0 : C) (C1 : obj C) := { + src : C1 ~> C0; tgt : C1 ~> C0 +}. +#[short(type="iHom")] +HB.structure Definition InternalHom {C: quiver} (C0 : C) := + { C1 of isInternalHom C C0 C1 }. + +Notation "X ':>' C" := (X : obj C) (at level 60, C at next level). + +(* HB.instance Definition _ (T : quiver) := Quiver.on (obj T). *) +(* HB.instance Definition _ (T : precat) := PreCat.on (obj T). *) +(* HB.instance Definition _ (T : cat) := Cat.on (obj T). *) +(* HB.instance Definition _ (T : pbcat) := PBCat.on (obj T). *) + +(* constructs the pullback from the cospan given by target and source. + Type-level construction: X and Y are two instances of the morphism + object, specified by (iHom C0), and are objects of (obj C). Here + 'iprod' is just an object of (obj C). The cospan is given by the + target of X and the source of Y. The pullback provides a commuting + square on the cospan, which basically ensures that the morphisms in + X and Y can be composed. *) +Definition iprod_pb {C: pbcat} {C0 : C} (X Y : iHom C0) : + span (X :> C) (Y :> C) := + pbk _ _ (Cospan (tgt : (X :> C) ~> C0) (src : (Y :> C) ~> C0)). + +Definition iprod {C: pbcat} {C0 : obj C} (X Y : iHom C0) : obj C := + bot (@iprod_pb C C0 X Y). +Notation "X *_ C0 Y" := (@iprod _ C0 (X : iHom C0) (Y : iHom C0)) + (at level 99, C0 at level 0, only parsing) : cat_scope. +Notation "X *_ C0 Y" := (@iprod _ C0 X Y) + (at level 99, C0 at level 0) : cat_scope. + +(* +(1) Defines pullback square (iprod_pb) + + X --- tgt -----> C0 + ^ ^ + | | + bot2left src + | | + X*Y - bot2right -> Y + + +(2) Defines source and target of the product (iprod_iHom) + + X --- src -----> C0 + ^ ^ + | | + iprodl tgt + | | + X*Y -- iprodr ---> Y +*) + +(* left and right projection morphisms of the product *) +Definition iprodl {C: pbcat} {C0 : C} (X Y : iHom C0) : + X *_C0 Y ~> (X :> C) := bot2left (iprod_pb X Y). +Definition iprodr {C: pbcat} {C0 : C} (X Y : iHom C0) : + X *_C0 Y ~> (Y :> C) := bot2right (iprod_pb X Y). + +(* Given (iHom C0) instances X and Y, we want to say that (X *_C0 Y) +is also an instance of (iHom C0). X and Y represent composable +morphisms, as by pullback properties, the diagram (1) commutes. +source and target are obtained by composing with product projections +(2) *) +Definition iprod_iHom {C: pbcat} {C0: C} (X Y: @iHom C C0) : + @isInternalHom C C0 (X *_C0 Y) := + @isInternalHom.Build C C0 (X *_C0 Y) + ((iprodl X Y) \; src) + ((iprodr X Y) \; tgt). + +HB.instance Definition iprod_iHom' {C: pbcat} {C0: C} (X Y: @iHom C C0) : + @isInternalHom C C0 (X *_C0 Y) := iprod_iHom X Y. + +(* the product as (iHom C0) object *) +Definition pbC0 (C : pbcat) (C0 : C) (X Y : iHom C0) : iHom C0 := + (X *_C0 Y) : iHom C0. + +(* we also define the trivial internal hom type *) +HB.instance Definition trivial_iHom {C: pbcat} {C0: C} : + @isInternalHom C C0 C0 := + isInternalHom.Build C C0 C0 idmap idmap. + +(**) + +Definition trivial_iHom' {C: pbcat} {C0: C} : @iHom C C0 := + InternalHom.Pack (InternalHom.Class (@trivial_iHom C C0)). + +Definition trivial_iprod_iHom {C: pbcat} {C0: C} : + @isInternalHom C C0 ((@trivial_iHom' C C0) *_C0 (@trivial_iHom' C C0)) := + @iprod_iHom' C C0 (@trivial_iHom' C C0) (@trivial_iHom' C C0). + +Definition trivial_iprod_iHom' {C: pbcat} {C0: C} : @iHom C C0 := + InternalHom.Pack (InternalHom.Class (@trivial_iprod_iHom C C0)). + +(**) + +(* we need internal hom morphisms: +the ones that preserve sources and targets. +basically, we recast morphisms in (obj C) into some in (@iHom C C0), +i.e. into morphism between copies of C1 *) +HB.mixin Record IsInternalHomHom {C: pbcat} (C0 : C) + (C1 C1' : @iHom C C0) (f : (C1 :> C) ~> (C1' :> C)) := { + hom_src : f \; (@src C C0 C1') = (@src C C0 C1); + hom_tgt : f \; tgt = tgt; +}. +#[short(type="iHomHom")] +HB.structure Definition InternalHomHom {C: pbcat} + (C0 : C) (C1 C1' : @iHom C C0) := + { f of @IsInternalHomHom C C0 C1 C1' f }. + +(* internal homs form a category, + the morphisms are the one that preserve source and target *) +HB.instance Definition iHom_quiver {C: pbcat} (C0 : C) : + IsQuiver (@iHom C C0) := + IsQuiver.Build (@iHom C C0) (@iHomHom C C0). + +Program Definition pre_iHom_id {C: pbcat} (C0 : C) (C1 : @iHom C C0) : + @IsInternalHomHom C C0 C1 C1 idmap := + @IsInternalHomHom.Build C C0 C1 C1 idmap _ _. +Obligation 1. +setoid_rewrite comp1o; reflexivity. +Defined. +Obligation 2. +setoid_rewrite comp1o; reflexivity. +Defined. + +Program Definition iHom_id {C: pbcat} (C0 : C) (C1 : @iHom C C0) : + C1 ~>_(@iHom C C0) C1 := + @InternalHomHom.Pack C C0 C1 C1 idmap _. +(* +The term "pre_iHom_id C1" has type "IsInternalHomHom.phant_axioms idmap" +while it is expected to have type "InternalHomHom.axioms_ ?sort". +*) +Obligation 1. +econstructor. +eapply (@pre_iHom_id C C0 C1). +Defined. + +Program Definition pre_iHom_comp {C: pbcat} (C0 : C) (C1 C2 C3: @iHom C C0) + (f: C1 ~>_(@iHom C C0) C2) (g: C2 ~>_(@iHom C C0) C3) : + @IsInternalHomHom C C0 C1 C3 (f \; g) := + @IsInternalHomHom.Build C C0 C1 C3 (f \; g) _ _. +Obligation 1. +setoid_rewrite <- compoA. +repeat (setoid_rewrite hom_src); auto. +Defined. +Obligation 2. +setoid_rewrite <- compoA. +repeat (setoid_rewrite hom_tgt); auto. +Defined. + +Program Definition iHom_comp {C: pbcat} (C0 : C) (C1 C2 C3: @iHom C C0) + (f: C1 ~>_(@iHom C C0) C2) (g: C2 ~>_(@iHom C C0) C3) : + C1 ~>_(@iHom C C0) C3 := + @InternalHomHom.Pack C C0 C1 C3 (f \; g) _. +Obligation 1. +econstructor. +eapply (@pre_iHom_comp C C0 C1 C2 C3 f g). +Defined. + +Program Definition iHom_precat {C: pbcat} (C0 : C) : + Quiver_IsPreCat (@iHom C C0) := + Quiver_IsPreCat.Build (@iHom C C0) _ _. +Obligation 1. +eapply (@iHom_id C C0 a). +Defined. +Obligation 2. +Show. +eapply (@iHom_comp C C0 _ _ _ H H0). +Defined. + +HB.instance Definition iHom_precat' {C: pbcat} (C0 : C) := iHom_precat C0. + +Lemma iHom_LeftUnit_lemma (C : pbcat) (C0 : C) + (a b : iHom C0) (f : a ~> b) : idmap \; f = f. +unfold idmap; simpl. +unfold iHom_precat_obligation_1. +unfold comp; simpl. +unfold iHom_precat_obligation_2. +unfold iHom_comp. +remember f as f1. +remember a as a1. +remember b as b1. +destruct f as [ff class]. +destruct a as [Ca class_a]. +destruct b as [Cb class_b]. +destruct class_a as [IMa]. +destruct class_b as [IMb]. +destruct class as [IM]. +destruct IMa. +destruct IMb. +destruct IM. +unfold obj in *. +simpl in *; simpl. + +eassert ( forall x, exists y, + {| + InternalHomHom.sort := idmap \; f1; + InternalHomHom.class := x + |} = + {| + InternalHomHom.sort := f1; + InternalHomHom.class := y + |} ) as A2. +{ rewrite Heqf1; simpl. + rewrite comp1o. + intros. + destruct x as [X]. + econstructor. + destruct X. + reflexivity. +} + +setoid_rewrite Heqf1 at 3. +specialize (A2 (iHom_comp_obligation_1 (iHom_id a1) f1)). +destruct A2. +rewrite H. + +inversion Heqf1; subst. +simpl. +destruct x as [IM]. +destruct IM. + +assert (hom_src0 = hom_src1) as D1. +{ eapply Prop_irrelevance. } + +assert (hom_tgt0 = hom_tgt1) as D2. +{ eapply Prop_irrelevance. } + +rewrite D1. +rewrite D2. +reflexivity. +Qed. + +Lemma iHom_RightUnit_lemma (C : pbcat) (C0 : C) + (a b : iHom C0) (f : a ~> b) : f \; idmap = f. +unfold idmap; simpl. +unfold iHom_precat_obligation_1. +unfold comp; simpl. +unfold iHom_precat_obligation_2. +unfold iHom_comp. +remember f as f1. +remember a as a1. +remember b as b1. +destruct f as [ff class]. +destruct a as [Ca class_a]. +destruct b as [Cb class_b]. +destruct class_a as [IMa]. +destruct class_b as [IMb]. +destruct class as [IM]. +destruct IMa. +destruct IMb. +destruct IM. +unfold obj in *. +simpl in *; simpl. + +eassert ( forall x, exists y, + {| + InternalHomHom.sort := f1 \; idmap; + InternalHomHom.class := x + |} = + {| + InternalHomHom.sort := f1; + InternalHomHom.class := y + |} ) as A2. +{ rewrite Heqf1; simpl. + rewrite compo1. + intros. + destruct x as [X]. + econstructor. + destruct X. + reflexivity. +} + +setoid_rewrite Heqf1 at 3. +specialize (A2 (iHom_comp_obligation_1 f1 (iHom_id b1))). +destruct A2. +rewrite H. + +inversion Heqf1; subst. +simpl. +destruct x as [IM]. +destruct IM. + +assert (hom_src0 = hom_src1) as D1. +{ eapply Prop_irrelevance. } + +assert (hom_tgt0 = hom_tgt1) as D2. +{ eapply Prop_irrelevance. } + +rewrite D1. +rewrite D2. +reflexivity. +Qed. + +Lemma iHom_Assoc_lemma {C : pbcat} (C0 : C) + (a b c d : iHom C0) (f : a ~> b) (g : b ~> c) (h : c ~> d) : + f \; g \; h = (f \; g) \; h. + unfold comp; simpl. + unfold iHom_precat_obligation_2; simpl. + unfold iHom_comp; simpl. + remember f as f1. + remember g as g1. + remember h as h1. + destruct f as [M_f class_f]. + destruct g as [M_g class_g]. + destruct h as [M_h class_h]. + destruct class_f as [IM_f]. + destruct class_g as [IM_g]. + destruct class_h as [IM_h]. + destruct IM_f. + destruct IM_g. + destruct IM_h. + unfold obj in *; simpl in *; simpl. + + eassert ( forall x y, + {| InternalHomHom.sort := f1 \; g1 \; h1; + InternalHomHom.class := x |} = + {| InternalHomHom.sort := (f1 \; g1) \; h1; + InternalHomHom.class := y |} ) as A2. + { rewrite Heqf1; simpl. + rewrite compoA. + intros. + destruct x as [X]. + destruct y as [Y]. + destruct X. + destruct Y. + + assert (hom_src3 = hom_src4) as D1. + { eapply Prop_irrelevance. } + + assert (hom_tgt3 = hom_tgt4) as D2. + { eapply Prop_irrelevance. } + + rewrite D1. + rewrite D2. + reflexivity. + } + + setoid_rewrite A2. + reflexivity. +Qed. + +Program Definition iHom_cat {C: pbcat} (C0 : C) : + PreCat_IsCat (@iHom C C0) := + PreCat_IsCat.Build (@iHom C C0) _ _ _. +Obligation 1. +eapply iHom_LeftUnit_lemma; eauto. +Qed. +Obligation 2. +eapply iHom_RightUnit_lemma; eauto. +Qed. +Obligation 3. +eapply iHom_Assoc_lemma; eauto. +Qed. + +(* Now we define an internal quiver as an object C0, + which has a C1 : iHom C0 attached to it *) +HB.mixin Record IsPreInternalQuiver (C : quiver) (C0 : obj C) := + { C1 : obj C }. +HB.structure Definition PreInternalQuiver C := + { C0 of @IsPreInternalQuiver C C0 }. + +Arguments C1 {C s}. + +#[wrapper] HB.mixin Record IsInternalQuiver (C : quiver) (C0 : obj C) of + @PreInternalQuiver C C0 := { + priv: @InternalHom C C0 (@C1 _ C0) + }. +#[short(type="iquiver")] +HB.structure Definition InternalQuiver (C : quiver) := + { C0 of IsInternalQuiver C C0 }. + +Coercion iquiver_quiver (C : quiver) (C0 : iquiver C) : C := C0 :> C. +Coercion iquiver_precat (C : precat) (C0 : iquiver C) : C := C0 :> C. +Coercion iquiver_cat (C : cat) (C0 : iquiver C) : C := C0 :> C. + +Definition jmcomp {C: cat} {a b c d: C} (e: c = b) (f: a ~> b) (g: c ~> d) := + f \; match e with eq_refl => g end. +Notation "f \;;_ e g" := (@jmcomp _ _ _ _ _ e f g) + (at level 60, g at level 60, e at level 0, format "f \;;_ e g", + only parsing) : cat_scope. + +Lemma pbsquare_universal {C: cat} (A B T P0 P1 : C) + (t: A ~> T) (s: B ~> T) (p1: P0 ~> A) (p2: P0 ~> B) + (f: P1 ~> A) (g: P1 ~> B) : + pbsquare p1 p2 t s -> + f \; t = g \; s -> + sigma m: P1 ~> P0, f = m \; p1 /\ g = m \; p2. + intros sq E. + destruct sq as [IM1 IM2]. + + remember (Span p1 p2) as Spn0. + remember (@Cospan C A B T t s) as Csp. + remember (@Span C A B P1 f g) as Spn1. + + destruct IM1 as [IM3]. + destruct IM2 as [IM4]. + + assert (bot2left Spn1 \; left2top Csp = bot2right Spn1 \; right2top Csp) + as K1. + { unfold bot2left, bot2right. + rewrite HeqCsp. + rewrite HeqSpn1. + simpl; auto. + } + remember ( @isPrePullback.Build C A B Csp Spn1 K1) as Pb1. + assert (PrePullback.axioms_ Csp Spn1) as Pb2. + { econstructor. + exact Pb1. } + remember ( @PrePullback.Pack C A B Csp Spn1 Pb2) as PB. + + destruct IM4 as [IM5 IM6]. + clear IM6. + specialize (IM5 PB). + + inversion HeqSpn1; subst. + simpl in *. + clear H K1. + + unfold pb_terminal in *. + destruct Pb2 as [IM]. + destruct IM. + simpl in *. + + destruct IM5. + simpl in *. + + econstructor. + instantiate (1:= bot_map). + split; auto. +Qed. + +Lemma jm_pbsquare_universal {C: cat} (A B T P0 P1 P2 : C) + (t: A ~> T) (s: B ~> T) (p1: P0 ~> A) (p2: P0 ~> B) + (f: P1 ~> A) (g: P1 ~> B) + (sq: pbsquare p1 p2 t s) + (E0: f \; t = g \; s) + (e: P0 = P2) : + sigma m: P1 ~> P2, f = m \;;_e p1 /\ g = m \;;_e p2. + unfold jmcomp. + destruct e. +(* dependent destruction e. *) + eapply pbsquare_universal; eauto. +Qed. + +Lemma pbquare_universal_aux1 {C: cat} (A0 A1 B0 B1 P0 P1 T : C) + (t: A0 ~> T) (s: B0 ~> T) (p01: P0 ~> A0) (p02: P0 ~> B0) + (f: A1 ~> A0) (g: B1 ~> B0) (p11: P1 ~> A1) (p12: P1 ~> B1) : + pbsquare p01 p02 t s -> + p11 \; f \; t = p12 \; g \; s -> + sigma m: P1 ~> P0, p11 \; f = m \; p01 /\ p12 \; g = m \; p02. + intros. + eapply pbsquare_universal; eauto. + setoid_rewrite <- compoA; auto. +Qed. + +(* Lemma is_pullback_in_pbcat {C: pbcat} *) + +(* +Set Debug "unification". +Lemma ... +Proof. + Fail ... +*) + +Lemma pbk_eta {C: pbcat} {C0} (X Y: iHom C0) : + (pbk (X :> C) (Y :> C) (Cospan (@tgt C C0 X) (@src C C0 Y))) = + (Span (iprodl X Y) (iprodr X Y)). + unfold iprodl, iprodr, iprod. + unfold iprod_pb; simpl. + + generalize (pbk (X :> C) (Y :> C) {| top := C0; left2top := tgt; right2top := src |}). + intro s0. + destruct s0. + simpl; auto. +Qed. + +Lemma pbk_pullback_is_pullback {C: pbcat} {C0} (X Y: iHom C0) : + Pullback C (Cospan (@tgt C C0 X) (@src C C0 Y)) + (pbk (X :> C) (Y :> C) (Cospan (@tgt C C0 X) (@src C C0 Y))) = + Pullback C (Cospan (@tgt C C0 X) (@src C C0 Y)) + (Span (iprodl X Y) (iprodr X Y)). + rewrite pbk_eta. + auto. +Qed. + +Lemma pbsquare_is_pullback_sym {C: pbcat} {C0} (X Y: iHom C0) : + Pullback C (Cospan (@tgt C C0 X) (@src C C0 Y)) + (pbk (X :> C) (Y :> C) (Cospan (@tgt C C0 X) (@src C C0 Y))) = + pbsquare (iprodl X Y) (iprodr X Y) (@tgt C C0 X) (@src C C0 Y). + rewrite pbk_pullback_is_pullback; auto. +Qed. + +Lemma pbsquare_is_pullback {C: pbcat} {C0} (X Y: iHom C0) : + pbsquare (iprodl X Y) (iprodr X Y) (@tgt C C0 X) (@src C C0 Y) = + Pullback C (Cospan (@tgt C C0 X) (@src C C0 Y)) + (pbk (X :> C) (Y :> C) (Cospan (@tgt C C0 X) (@src C C0 Y))). + rewrite pbk_pullback_is_pullback; auto. +Qed. + + +Program Definition ipairC {C : pbcat} {C0 : C} {x0 x1 x2 x3 : iHom C0} + (f : x0 ~>_(iHom C0) x2) (g : x1 ~>_(iHom C0) x3) : + (x0 *_C0 x1 :> C) ~>_C (x2 *_C0 x3 :> C). + + remember (x0 *_ C0 x1 : iHom C0) as Pb1. + remember (x2 *_ C0 x3 : iHom C0) as Pb2. + + remember (@Cospan C (x0 :> C) (x1 :> C) C0 + (@tgt C C0 x0) (@src C C0 x1)) as Csp1. + + remember (@Cospan C (x2 :> C) (x3 :> C) C0 + (@tgt C C0 x2) (@src C C0 x3)) as Csp2. + + set (src0 := @src C C0 x0). + set (tgt0 := @tgt C C0 x0). + + set (src1 := @src C C0 x1). + set (tgt1 := @tgt C C0 x1). + + set (src2 := @src C C0 x2). + set (tgt2 := @tgt C C0 x2). + + set (src3 := @src C C0 x3). + set (tgt3 := @tgt C C0 x3). + + remember (@src C C0 (x0 *_C0 x1)) as src01. + remember (@tgt C C0 (x0 *_C0 x1)) as tgt01. + + remember (@src C C0 (x2 *_C0 x3)) as src23. + remember (@tgt C C0 (x2 *_C0 x3)) as tgt23. + + set (Sp1 := pbk (x0 :> C) (x1 :> C) Csp1). + set (Sp2 := pbk (x2 :> C) (x3 :> C) Csp2). + + assert (@Pullback C (x0 :> C) (x1 :> C) Csp1 Sp1) as PBa1. + { remember C as C'. + destruct C as [C class]. + destruct class as [A1 A2 A3 A4 A5 A6]. + destruct A6 as [B1]. + assert (pb (pbk (x0 :> C') (x1 :> C') Csp1)). + { inversion HeqC'; subst. + eapply B1; eauto. } + econstructor; eauto. + } + + assert (@Pullback C (x2 :> C) (x3 :> C) Csp2 Sp2) as PBa2. + { remember C as C'. + destruct C as [C class]. + destruct class as [A1 A2 A3 A4 A5 A6]. + destruct A6 as [B1]. + assert (pb (pbk (x2 :> C') (x3 :> C') Csp2)). + { inversion HeqC'; subst. + eapply B1; eauto. } + econstructor; eauto. + } + +(* assert (@Pullback C (x2 :> C) (x3 :> C) Csp2 Sp2) as PBa2. + admit. +*) + assert ((x0 *_ C0 x1) = bot Sp1) as E01. + { subst Sp1. + unfold iprod. + unfold iprod_pb. + rewrite HeqCsp1; auto. + } + + assert ((x2 *_ C0 x3) = bot Sp2) as E23. + { subst Sp2. + unfold iprod. + unfold iprod_pb. + rewrite HeqCsp2; auto. + } + + set (prj11 := @iprodl C C0 x0 x1). + set (prj12 := @iprodr C C0 x0 x1). + + set (prj21 := @iprodl C C0 x2 x3). + set (prj22 := @iprodr C C0 x2 x3). + + set (ff := prj11 \; f). + set (gg := prj12 \; g). + + assert ((f : (x0 :> C) ~>_C (x2 :> C)) \; tgt2 = tgt0) as E20. + { remember f as f1. + destruct f as [fsort fclass]. + destruct fclass as [fIM]. + destruct fIM. + inversion Heqf1; subst. + simpl in *; simpl; auto. + } + + assert ((g : (x1 :> C) ~>_C (x3 :> C)) \; src3 = src1) as E31. + { remember g as g1. + destruct g as [gsort gclass]. + destruct gclass as [gIM]. + destruct gIM. + inversion Heqg1; subst. + simpl in *; simpl; auto. + } + + assert (prj11 \; tgt0 = prj12 \; src1) as E11. + { destruct PBa1 as [C1 C2]. + destruct C1 as [C3]. + inversion HeqCsp1; subst. + simpl in *; auto. + } + + assert (ff \; tgt2 = gg \; src3) as E1. + { subst ff gg. + setoid_rewrite <- compoA. + rewrite E20. + rewrite E31. + exact E11. + } + + (* basically, follows from pbquare_universal and E1. + sordid eta-conversion issue fixed by pbsquare_is_pullback *) + assert (sigma m: ((x0 *_ C0 x1) ~>_C (x2 *_ C0 x3) :> C), + ff = m \; prj21 /\ gg = m \; prj22) as EM. + { eapply (@pbsquare_universal C) ; eauto. + + remember C as C'. + destruct C as [C class]. + destruct class as [A1 A2 A3 A4 A5 A6]. + destruct A6 as [B1]. + subst prj21 prj22. + + (* surprisingly, this does not work with pbsquare_is_pulback_sym *) + (* rewrite - pbsquare_is_pullback_sym. + Set Printing All. + *) + + rewrite pbsquare_is_pullback. + inversion HeqCsp2; subst. + subst Sp2. + exact PBa2. + } + + destruct EM as [mm [EM1 EM2]]. + exact mm. +Qed. + +Notation "<( f , g )>" := (ipairC f g). + + +(* nested product *) +Program Definition iprodCAsc {C : pbcat} {C0 : C} (c1 c2 c3 : iHom C0) : + (((c1 *_C0 c2 : iHom C0) *_C0 c3) :> C) ~>_C + ((c1 *_C0 (c2 *_C0 c3 : iHom C0) : iHom C0) :> C). + +set (src1 := @src C C0 c1). +set (src2 := @src C C0 c2). +set (src3 := @src C C0 c3). +set (tgt1 := @tgt C C0 c1). +set (tgt2 := @tgt C C0 c2). +set (tgt3 := @tgt C C0 c3). + +set (Pb12 := c1 *_ C0 c2 : iHom C0). +set (Pb23 := c2 *_ C0 c3 : iHom C0). +set (Pb15 := c1 *_ C0 Pb23 : iHom C0). +set (Pb33 := Pb12 *_ C0 c3 : iHom C0). + +set (j12L := iprodl c1 c2). +set (j12R := iprodr c1 c2). +set (j23L := iprodl c2 c3). +set (j23R := iprodr c2 c3). +set (j15L := iprodl c1 Pb23). +set (j15R := iprodr c1 Pb23). +set (j33L := iprodl Pb12 c3). +set (j33R := iprodr Pb12 c3). + +set (src23 := @src C C0 Pb23). +set (tgt23 := @tgt C C0 Pb23). +set (src12 := @src C C0 Pb12). +set (tgt12 := @tgt C C0 Pb12). +simpl. + +assert (src23 = j23L \; src2) as srcPb23. +{ subst src23 j23L src2. + auto. +} + +assert (tgt23 = j23R \; tgt3) as tgtPb23. +{ subst tgt23 j23R tgt3. + auto. +} + +assert (src12 = j12L \; src1) as srcPb12. +{ subst src12 j12L src1. + auto. +} + +assert (tgt12 = j12R \; tgt2) as tgtPb12. +{ subst tgt12 j12R tgt2. + auto. +} + +assert (j12L \; tgt1 = j12R \; src2) as sqPb12. +{ set (X := @is_ppbk C). + specialize (X (c1 :> C) (c2 :> C)). + specialize (X (Cospan tgt1 src2)). + destruct X as [X]. + simpl in X; auto. +} + +assert (j23L \; tgt2 = j23R \; src3) as sqPb23. +{ set (X := @is_ppbk C). + specialize (X (c2 :> C) (c3 :> C)). + specialize (X (Cospan tgt2 src3)). + destruct X as [X]. + simpl in X; auto. +} + +assert ((j33L \; j12R) \; tgt2 = j33R \; src3) as sqPb33. +{ assert (j33L \; tgt12 = j33R \; src3) as H. + { subst j33L j33R. + set (X := @is_ppbk C). + specialize (X (Pb12 :> C) (c3 :> C)). + specialize (X (Cospan tgt12 src3)). + destruct X as [X]. + simpl in X. + auto. + } + setoid_rewrite <- compoA. + rewrite tgtPb12 in H; auto. +} + +assert (pbsquare j23L j23R tgt2 src3) as pbsq23. +{ subst j23L j23R. + rewrite pbsquare_is_pullback. + + set (Csp23 := @Cospan C (c2 :> C) (c3 :> C) _ tgt2 src3). + + remember C as C'. + destruct C as [C class]. + destruct class as [A1 A2 A3 A4 A5 A6]. + destruct A6 as [B1]. + + assert (pb (pbk (c2 :> C') (c3 :> C') Csp23)) as X. + { inversion HeqC'; subst. + eapply B1; eauto. + } + econstructor; eauto. +} + +assert (j15L \; tgt1 = (j15R \; j23L) \; src2) as sqPb15. +{ assert (j15L \; tgt1 = j15R \; src23) as H. + { subst j15L j15R. + set (X := @is_ppbk C). + specialize (X (c1 :> C) (Pb23 :> C)). + specialize (X (Cospan tgt1 src23)). + destruct X as [X]. + simpl in X; auto. + } + setoid_rewrite <- compoA. + rewrite srcPb23 in H; auto. +} + + +assert (forall (e1: ((c2 *_C0 c3) :> C) = (Pb23 :> C)), + sigma (m23: (Pb33 :> C) ~> (Pb23 :> C)), + (j33L \; j12R = m23 \;;_e1 j23L) /\ (j33R = m23 \;;_e1 j23R)) + as M23. +{ intro e1. + subst Pb33. + + eapply (@jm_pbsquare_universal C (c2 :> C) (c3 :> C) C0 + (c2 *_ C0 c3 :> C) (Pb12 *_ C0 c3 :> C) (Pb23 :> C) + tgt2 src3 j23L j23R (j33L \; j12R) j33R pbsq23 sqPb33 e1); eauto. +} + +assert (pbsquare j12L j12R tgt1 src2) as pbsq12. +{ subst j12L j12R. + rewrite pbsquare_is_pullback. + + set (Csp12 := @Cospan C (c1 :> C) (c2 :> C) _ tgt1 src2). + + remember C as C'. + destruct C as [C class]. + destruct class as [A1 A2 A3 A4 A5 A6]. + destruct A6 as [B1]. + + assert (pb (pbk (c1 :> C') (c2 :> C') Csp12)) as X. + { inversion HeqC'; subst. + eapply B1; eauto. + } + econstructor; eauto. +} + +assert (forall (e1: ((c1 *_C0 c2) :> C) = (Pb12 :> C)), + sigma (m12: (Pb15 :> C) ~> (Pb12 :> C)), + (j15L = m12 \;;_e1 j12L) /\ (j15R \; j23L = m12 \;;_e1 j12R)) + as M12. +{ intro e1. + subst Pb15. + + eapply (@jm_pbsquare_universal C (c1 :> C) (c2 :> C) C0 + (c1 *_ C0 c2 :> C) (c1 *_ C0 Pb23 :> C) (Pb12 :> C) + tgt1 src2 j12L j12R j15L (j15R \; j23L) pbsq12 sqPb15 e1); eauto. +} + +assert (((c1 *_C0 c2) :> C) = Pb12) as E12. +{ auto. } +destruct (M12 E12) as [m12 [m12_E m12_U]]. + +assert (((c2 *_C0 c3) :> C) = Pb23) as E23. +{ auto. } +destruct (M23 E23) as [m23 [m23_E m23_U]]. + +assert (forall (e2: ((c2 *_C0 c3) :> C) = Pb23), + j33L \; (j12R \; src2) = m23 \;;_e2 j23L \; src2) as M23_E1. +{ intros e2. + unfold jmcomp. + destruct e2. +(* dependent destruction e2. *) + rewrite compoA. + rewrite m23_E. + unfold jmcomp. +(* clear -E23. + rewrite -compoA. + congr (_ \; _ \; _). + Set Printing All. + case: _ / E23. + do [destruct E23] in j23L m23 *. *) + dependent destruction E23. + rewrite compoA; auto. +} + +assert (forall (e3: ((c2 *_C0 c3) :> C) = Pb23), + (j33L \; j12L) \; tgt1 = m23 \;;_e3 j23L \; src2) as M23_E2. +{ intros e3. + specialize (M23_E1 E23). + unfold jmcomp in M23_E1. + destruct E23. +(* dependent destruction E23. *) + unfold jmcomp. + dependent destruction e3. + setoid_rewrite <- compoA. + rewrite sqPb12. + rewrite M23_E1; auto. +} + +assert (pbsquare j15L j15R tgt1 src23) as pbsq15. +{ set (Csp15 := + @Cospan C (c1 :> C) (Pb23 :> C) _ tgt1 (j23L \; src2)). + + subst j15L j15R. + rewrite pbsquare_is_pullback. + + remember C as C'. + destruct C as [C class]. + destruct class as [A1 A2 A3 A4 A5 A6]. + destruct A6 as [B1]. + assert (pb (pbk (c1 :> C') (Pb23 :> C') Csp15)) as X. + { inversion HeqC'; subst. + eapply B1; eauto. } + econstructor; eauto. +} + +assert ((j33L \; j12L) \; tgt1 = m23 \; src23) as sqM23. +{ specialize (M23_E2 E23). + dependent destruction E23. + exact M23_E2. +} + +assert ((((c1 *_ C0 c2) *_ C0 c3) :> C) = Pb33) as E33. +{ auto. } + +assert ( + forall (e1: (((c1 *_ C0 c2) *_ C0 c3) :> C) = Pb33), + sigma mm: ((c1 *_ C0 c2) *_ C0 c3) ~> (c1 *_ C0 (c2 *_ C0 c3)), + (j33L \; j12L = mm \; j15L) /\ (idmap \;;_e1 m23 = mm \; j15R)) as X. +{ intro e1. + unfold jmcomp. + dependent destruction e1. + rewrite comp1o. + subst Pb12. + eapply (@pbsquare_universal C _ _ _ _ _ _ _ _ _ (j33L \; j12L) m23). + exact pbsq15. + exact sqM23. +} +destruct (X E33) as [mm R]. +exact mm. +Qed. + + +(* An internal precategory is an internal category with two operators + that must be src and tgt preserving, i.e. iHom morphisms: identity + : C0 -> C1 (corresponding to horizontal 1-morphism identity in + double cat) and composition : C1 * C1 -> C1 (corresponding to + horizontal composition) *) + +(*Set Printing All.*) (* bug in elpi 2.0.1 *) +HB.mixin Record IsInternalPreCat (C : pbcat) (C0 : obj C) + of @InternalQuiver C C0 := { + iidI : (C0 : iHom C0) ~>_(iHom C0) (@C1 C C0 : iHom C0); + icompI : + + let C1 : iHom C0 := @C1 C C0 in + let C2 : iHom C0 := @pbC0 C C0 C1 C1 in + + (C2 ~>_(iHom C0) C1 ) +}. +(* bad +-------> G: PBCat.type +-------> G: (obj C) +-------> G: (@InternalQuiver.axioms_ C C0) +-------> G: (IsPreInternalQuiver.axioms_ (encatI_PBCat__to__cat_Quiver C) C0) +-------> G: (IsInternalQuiver.axioms_ (encatI_PBCat__to__cat_Quiver C) C0 + local_mixin_encatI_IsPreInternalQuiver) +-------> G: Type +-------> G: (@hom (@InternalHom.type (elpi.hole elpi.hole) C0) + (C0 : @InternalHom.type (elpi.hole elpi.hole) C0) + (@C1 C C0 : @InternalHom.type (elpi.hole elpi.hole) C0)) +-------> G: (let C1 := @C1 C C0 in + let C2 := @pbC0 C C0 C1 C1 in +@hom (@InternalHom.type (elpi.hole C2 C1 elpi.hole) C0) C2 C1) + + + + +-------> G: PBCat.type +-------> G: (obj C) +-------> G: (@InternalQuiver.axioms_ C C0) +-------> G: (IsPreInternalQuiver.axioms_ (encatI_PBCat__to__cat_Quiver C) C0) +-------> G: (IsInternalQuiver.axioms_ (encatI_PBCat__to__cat_Quiver C) C0 + local_mixin_encatI_IsPreInternalQuiver) +-------> G: Type +-------> G: (@hom (@InternalHom.type (elpi.hole elpi.hole) C0) + (C0 : @InternalHom.type (elpi.hole elpi.hole) C0) + (@C1 C C0 : @InternalHom.type (elpi.hole elpi.hole) C0)) +-------> G: (let C1 : @InternalHom.type (elpi.hole elpi.hole) C0 := @C1 C C0 in + let C2 : @InternalHom.type (elpi.hole C1 elpi.hole) C0 := + @pbC0 C C0 C1 C1 in + @hom (@InternalHom.type (elpi.hole C2 C1 elpi.hole) C0) C2 C1) + *) + +#[short(type="iprecat")] +HB.structure Definition InternalPreCat (C : pbcat) := + { C0 of @IsInternalPreCat C C0 }. + +Unset Printing All. + +Program Definition iidC' {C : pbcat} {C0 : iprecat C} : + ((C0 : iHom C0) :> C) ~>_C + ((@C1 C C0 : iHom C0) :> C). +destruct C0; simpl in *. +destruct class as [IM1 IM2 IM3]; simpl in *. +destruct IM3; simpl in *. +exact iidI0. +Defined. +Program Definition iidC {C : pbcat} {C0 : iprecat C} : + (C0 :> C) ~>_C (@C1 C C0 :> C). +eapply iidC'; eauto. +Defined. + +Program Definition icompC {C : pbcat} {C0 : iprecat C} : + let C1 := @C1 C C0 : iHom C0 in + let C2 := pbC0 C1 C1 : iHom C0 in + ((C2 :> C) ~>_C (C1 :> C)). +destruct C0; simpl in *. +destruct class as [IM1 IM2 IM3]; simpl in *. +destruct IM3; simpl in *. +exact icompI0. +Defined. + +(* Check (iquiver Type <~> quiver). *) +(* Check (iprecat Type <~> precat). *) + +(* An internal category moreover must satisfy additional properies on +iid and icomp (associativity and unit laws) *) +#[key="C0"] + HB.mixin Record IsInternalCat (C : pbcat) (C0 : obj C) + of InternalPreCat C C0 := { + icompA1 : + (<( (@icompI C C0), + (@idmap (iHom C0) (@C1 C C0: iHom C0)) )> \; icompC) = + ((@iprodCAsc C C0 (@C1 C C0: iHom C0) _ _) \; + <( (@idmap (iHom C0) (@C1 C C0: iHom C0)), icompI )> \; icompC) ; + + icomp1l : <( @idmap (iHom C0) (@C1 C C0: iHom C0), (@iidI C C0) )> \; + icompC = @iprodl C C0 (C1 :> C) (C0 :> C); + + icomp1r : <( (@iidI C C0), @idmap (iHom C0) (@C1 C C0: iHom C0) )> \; + icompC = @iprodr C C0 (C0 :> C) (C1 :> C); + }. +#[short(type="icat")] +HB.structure Definition InternalCat (C : pbcat) := + {C0 of @IsInternalCat C C0}. +(* Check (icat Type <~> cat). *) + + +(************************************************************************) + +(** DEFINITION OF DOUBLE CATEGORY (based on internal category) *) + +(* A double category is an internal category in cat + - The objects are the objects of C0 + - The vertical maps are the maps of C0 + - The horizontal maps are the objects of C1 + - The 2-cells are the maps of C1 + + About identities: + - The identity vertical map on (x : C) is \idmap_x + - The identity horizontal map on (x : C) is iid x + - the identity 2-cell on (x : C) is iid (\idmap_x) = \idmap_(iid x) + + About compositions: + - The vertical composition of maps is the composition of C0 + - The vertical compositions of 2-cells is the composition of C1 + (and it agrees with the former because src and tgt are functors + and because iid is a iHom-map) + - The horizontal composition of maps is the object part of icomp + - The horizontal composition of 2-cells is the map part of icomp + *) +(* HB.structure' Definition DoubleCat := @InternalCat cat. *) + +(* this proof, so painful, why? *) +Lemma cat_pbop : HasPBop cat. + econstructor; intros A B H. + destruct H. + simpl in *. + unfold hom in *. + simpl in *. + + set (PB := (@commaE.ptype A B top left2top right2top : cat)). + + assert (PB ~> A) as L1. + { subst PB. + unfold hom. + simpl. + + set (ff := @pcat_prj1 A B top left2top right2top). + econstructor. + instantiate (1:=ff). + econstructor. + subst ff. + + eapply pcat_prj1_isFunctor. + } + + assert (PB ~> B) as R1. + { subst PB. + unfold hom. + simpl. + + set (ff := @pcat_prj2 A B top left2top right2top). + econstructor. + instantiate (1:=ff). + econstructor. + subst ff. + + eapply pcat_prj2_isFunctor. + } + + eexact (@Span cat A B PB L1 R1). +Qed. +HB.instance Definition _ := cat_pbop. + +Axiom cat_preb : + forall (a b: cat) (c: cospan a b), isPrePullback cat a b c (@pbk cat a b c). +HB.instance Definition _ (a b: cat) (c: cospan a b) := @cat_preb a b c. +Axiom cat_pb : + forall (a b: cat) (c: cospan a b), + prepullback_isTerminal cat a b c (@pbk cat a b c). +HB.instance Definition _ (a b: cat) (c: cospan a b) := @cat_pb a b c. + +(* basically, the internal category adds the D1 category to the base +D0 category, which is C0 (an object of cat, which is shown to have +pullbacks) *) +Definition doublecat := icat cat. + +(* Check (doublecat <~> ???) *) + +(* +Lemma cat_pbop : HasPBop cat. + econstructor; intros. + destruct A. + destruct class as [B1 B2 B3]. + destruct B1. + destruct H. + econstructor. +Admitted. +*) +(* +Program Definition pb_cat (A B: cat) (H: cospan A B) : cat. + remember A as a. + destruct a as [a_sort a_class]. + remember B as b. + destruct b as [b_sort b_class]. + remember H as H0. + destruct H as [t l r]. + + econstructor. + instantiate (1:= sigma (x: a_sort) (y: b_sort), ). + + + remember t as t0. + destruct t as [s c]. + destruct c as [a1 a2 a3]. + econstructor. +*) + + diff --git a/theories/encatI0.v b/theories/encatI0.v new file mode 100644 index 000000000..8fbcc8fa9 --- /dev/null +++ b/theories/encatI0.v @@ -0,0 +1,522 @@ +Require Import ssreflect ssrfun. +Unset Universe Checking. +From HB Require Import structures cat. +Set Universe Checking. +Require Import Coq.Program.Equality. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. +Add Search Blacklist "__canonical__". + +Local Open Scope algebra_scope. + +Local Open Scope cat_scope. + +(* +Notation "'sigma' x .. y , p" := + (sigT (fun x => .. (sigT (fun y => p)) ..)) + (at level 200, x binder, right associativity, + format "'[' 'sigma' '/ ' x .. y , '/ ' p ']'") + : type_scope. +*) + +(*** CATEGORIES WITH PULLBACKS *) + +(* category with all prepullbacks *) +(* Ideally span is in fact expanded and the final mixin has +a pb : forall A B, cospan A B -> C +but it is not clear how to do that yet +*) +HB.mixin Record HasPBop C of Cat C := { + pbk : forall (A B: C), cospan A B -> span A B + }. +#[short(type="pbop")] +HB.structure Definition PBop := + {C of HasPBop C & PreCat C }. + +(* category with all pullbacks *) +(* Wrong: we don't wrap classes, only mixins *) +#[wrapper] +HB.mixin Record HasPreBCat C of PBop C : Type := { + is_ppbk : forall (a b : C) (c : cospan a b), + isPrePullback C a b c (@pbk C a b c) + }. +#[short(type="pbcat")] +HB.structure Definition PreBCat := + {C of HasPreBCat C}. + +#[wrapper] +HB.mixin Record HasPBCat C of PBop C & HasPreBCat C : Type := { + is_tpbk : forall (a b : C) (c : cospan a b), + prepullback_isTerminal C a b c (@pbk C a b c) + }. +#[short(type="pbcat")] +HB.structure Definition PBCat := + {C of HasPBCat C}. + + +(************************************************************************) + +(* AUXILIARY for pullbacks *) + +Definition comm_square {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) {B: Q} (p1: B ~> L) (p2: B ~> R) : Prop := + p1 \; l = p2 \; r. + +Definition comm_triangle {Q: precat} {A B C: Q} + (h: A ~> C) (f: A ~> B) (g: B ~> C) : Prop := + h = f \; g. + +Record GMedArrow {Q: precat} + (* cospan *) + {L R T: Q} (l: L ~> T) (r: R ~> T) + (* span (for the pullback) *) + {B: Q} (p1: B ~> L) (p2: B ~> R) + (* another object *) + {B0: Q} + (* mediating morphism from B0 to B *) + (m: B0 ~> B) := { + gmedarrow_prop : forall (p01: B0 ~> L) (p02: B0 ~> R), + @comm_square Q L R T l r B0 p01 p02 -> + comm_triangle p01 m p1 /\ comm_triangle p02 m p2 +}. + +(************************************************************************) + +(* PULLBACKS *) + +(* Span pinned to an object *) +HB.mixin Record IsPSpan {Q: precat} + {L R T: Q} (l: L ~> T) (r: R ~> T) (B: Q) : Type := { + lprj : B ~> L ; + rprj : B ~> R + }. +#[short(type="pspan"), verbose] +HB.structure Definition PSpan {Q: precat} + {L R T : Q} (l: L ~> T) (r: R ~> T) := + { B of IsPSpan Q L R T l r B }. + +Definition medarrow_prop {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) + (B: @pspan Q L R T l r) + {B0: Q} (m: B0 ~> PSpan.sort B) : Prop := + @GMedArrow Q L R T l r B lprj rprj B0 m. + +Definition has_medarrow {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) + (B: @pspan Q L R T l r) + (B0: Q) : Type := sigma m, @medarrow_prop Q L R T l r B B0 m. + +Definition medarrow_is_unique {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) + (B: @pspan Q L R T l r) {B0: Q} : Prop := + forall (m m': B0 ~> PSpan.sort B), + @medarrow_prop Q L R T l r B B0 m -> + @medarrow_prop Q L R T l r B B0 m' -> m = m'. + +HB.mixin Record IsPrePBack (Q: precat) (L R T: Q) (l: L ~> T) (r: R ~> T) + (B: Q) of IsPSpan Q L R T l r B : Type := { + comm_sq : comm_square l r (@lprj Q L R T l r B) rprj ; + }. +#[short(type="prepback"), verbose] +HB.structure Definition PrePBack (Q: precat) + (L R T : Q) (l: L ~> T) (r: R ~> T) := + { B of IsPrePBack Q L R T l r B & }. + +HB.status. +(* BUG: IsPrePBack -> IsPSpan missing down here? It is there before *) +#[verbose] +HB.mixin Record IsPBack (Q: precat) (L R T: Q) (l: L ~> T) (r: R ~> T) + (B: Q) of (*IsPrePBack Q L R T l r B*) PrePBack Q l r B : Type := { + has_umarrow : forall B0: Q, @has_medarrow Q L R T l r B B0 + * @medarrow_is_unique Q L R T l r B B0 + }. +#[short(type="pback"), verbose] +HB.structure Definition PBack (Q: precat) + {L R T : Q} (l: L ~> T) (r: R ~> T) := + { B of IsPBack Q L R T l r B }. + +(* +(* packs all the definition together *) +HB.mixin Record IsPBack2 (Q: precat) (L R T: Q) (l: L ~> T) (r: R ~> T) + (B: @pspan Q L R T l r) : Type := { + comm_sq : comm_square l r (@lprj Q L R T l r B) rprj ; + has_umarrow : forall B0: Q, @has_medarrow Q L R T l r B B0 + * @medarrow_is_unique Q L R T l r B B0 + }. +#[short(type="pback2"), verbose] +HB.structure Definition PBack2 (Q: precat) + {L R T : Q} (l: L ~> T) (r: R ~> T) := + { B of IsPBack2 Q L R T l r B }. +*) + +(***********************************************************************) + +(*** alternative CATEGORIES WITH PULLBACKS *) + +(* category with all pullbacks *) +HB.mixin Record HasPBKop C of Cat C := { + pbkop : forall {L R T: C} (l: L ~> T) (r: R ~> T), C + }. +#[short(type="pbkop")] +HB.structure Definition PBKop := + {C of HasPBKop C & PreCat C }. + +#[wrapper] +HB.mixin Record HasPreSpanCat C of PBKop C : Type := { + has_prespan : forall {L R T: C} (l: L ~> T) (r: R ~> T), + @IsPSpan C L R T l r (@pbkop C L R T l r) + }. +#[short(type="prespancat")] +HB.structure Definition PreSpanCat := + {C of HasPreSpanCat C}. + +#[wrapper] +HB.mixin Record HasPrePBKcat C of PreSpanCat C : Type := { + has_prepbk : forall {L R T: C} (l: L ~> T) (r: R ~> T), + @IsPrePBack C L R T l r (@pbkop C L R T l r) + }. +#[short(type="prepbkcat")] +HB.structure Definition PrePBKcat := + {C of HasPrePBKcat C}. + +(* category with all pullbacks *) +#[wrapper] +HB.mixin Record HasPBKcat C of PrePBKcat C := { + has_pbk : forall {L R T: C} (l: L ~> T) (r: R ~> T), + @IsPBack C L R T l r (@pbkop C L R T l r) + }. +#[short(type="pbkcat")] +HB.structure Definition PBKcat := + {C of HasPBKcat C & PreCat C }. + +(* +(* on the other hand, this works... *) +#[wrapper] +HB.mixin Record HasPBK2cat C of PBKop C := { + is_gpbk2 : forall {L R T: C} (l: L ~> T) (r: R ~> T), + @IsPBack2 C L R T l r (@pbkop C L R T l r) + }. +#[short(type="pbk2cat")] +HB.structure Definition PBK2cat := + {C of HasPBK2cat C & PreCat C }. +*) + +(***********************************************************************) + +HB.mixin Record isInternalHom {C: quiver} (C0 : C) (C1 : obj C) := { + src : C1 ~> C0; tgt : C1 ~> C0 +}. +#[short(type="iHom")] +HB.structure Definition InternalHom {C: quiver} (C0 : C) := + { C1 of isInternalHom C C0 C1 }. + +Notation "X ':>' C" := (X : obj C) (at level 60, C at next level). + +Definition iprod {C: pbkcat} {C0 : C} (X Y : iHom C0) : C := +(* pspan (@tgt C C0 (X :> C)) (@src C C0 (Y :> C)) := *) + @pbkop C (X :> C) (Y :> C) C0 (tgt : (X :> C) ~> C0) (src : (Y :> C) ~> C0). + +(* could be problematic... *) +Program Definition iprod_pspan {C: pbkcat} {C0 : obj C} (X Y : iHom C0) : + pspan (@tgt C C0 (X :> C)) (@src C C0 (Y :> C)). +set (x := @iprod C C0 X Y). +destruct C. +destruct class as [A0 A1 A2 A3 A4 A5 A6]. +destruct A4 as [IM]. +econstructor. +econstructor. +eapply IM. +Defined. + +Program Definition iprod_pbk {C: pbkcat} {C0 : obj C} (X Y : iHom C0) : + pback (@tgt C C0 (X :> C)) (@src C C0 (Y :> C)). +set (x := @iprod C C0 X Y). +destruct C. +destruct class as [A0 A1 A2 A3 A4 A5 A6]. +destruct A6 as [IM]. +econstructor. +econstructor. +eapply IM. +Defined. + +Notation "X *_ C0 Y" := (@iprod _ C0 (X : iHom C0) (Y : iHom C0)) + (at level 99, C0 at level 0, only parsing) : encat_scope. +Notation "X *_ C0 Y" := (@iprod _ C0 X Y) + (at level 99, C0 at level 0) : cat_scope. + +(*** PROBLEMATIC *) +(* left and right projection morphisms of the product *) +Program Definition iprodl {C: pbkcat} {C0 : C} (X Y : iHom C0) : + X *_C0 Y ~> (X :> C). +remember C as C'. +destruct C'. +destruct class as [A0 A1 A2 A3 A4 A5 A6]. +destruct A4 as [IM]. +destruct X as [J1 J2]. +destruct Y as [I1 I2]. +simpl in *. +simpl. +unfold iprod. +simpl. +(* specialize (IM J1 I1 C0). *) +Admitted. +Fail Definition iprodr {C: pbcat} {C0 : C} (X Y : iHom C0) : + X *_C0 Y ~> (Y :> C) := bot2right (iprod_pb X Y). + +Fail Definition iprod_iHom {C: pbkcat} {C0: C} (X Y: @iHom C C0) : + @isInternalHom C C0 (X *_C0 Y) := + @isInternalHom.Build C C0 (X *_C0 Y) + ((iprodl X Y) \; src) + ((iprodr X Y) \; tgt). + +Fail HB.instance Definition iprod_iHom' {C: pbcat} {C0: C} (X Y: @iHom C C0) : + @isInternalHom C C0 (X *_C0 Y) := iprod_iHom X Y. + +(* the product as (iHom C0) object *) +Fail Definition pbC0 (C : pbcat) (C0 : C) (X Y : iHom C0) : iHom C0 := + (X *_C0 Y) : iHom C0. + + + +(*** OLDER VERSION, even worse *************************************) +(* doesn't avoid repetition, comment out previous version to run *) + +(* PULLBACKS *) + +(* Span pinned to an object *) +HB.mixin Record IsPSpan {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) (B: Q) : Type := { + lprj : B ~> L ; + rprj : B ~> R + }. +#[short(type="pspan"), verbose] +HB.structure Definition PSpan {Q: precat} + {L R T : Q} (l: L ~> T) (r: R ~> T) := + { B of IsPSpan Q L R T l r B }. + +Definition medarrow_prop {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) + (B: @pspan Q L R T l r) + {B0: Q} (m: B0 ~> PSpan.sort B) : Prop := + @GMedArrow Q L R T l r (@comm_square Q L R T l r) B lprj rprj B0 m. + +Definition has_medarrow {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) + (B: @pspan Q L R T l r) + (B0: Q) : Type := sigma m, @medarrow_prop Q L R T l r B B0 m. + +Definition medarrow_is_unique {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) + (B: @pspan Q L R T l r) {B0: Q} : Prop := + forall (m m': B0 ~> PSpan.sort B), + @medarrow_prop Q L R T l r B B0 m -> + @medarrow_prop Q L R T l r B B0 m' -> m = m'. + +HB.mixin Record IsPrePBack (Q: precat) (L R T: Q) (l: L ~> T) (r: R ~> T) + (B: @pspan Q L R T l r) : Type := { + comm_sq : comm_square l r (@lprj Q L R T l r B) rprj ; + }. +#[short(type="prepback"), verbose] +HB.structure Definition PrePBack (Q: precat) + {L R T : Q} (l: L ~> T) (r: R ~> T) := + { B of IsPrePBack Q L R T l r B }. + +HB.mixin Record IsPBack (Q: precat) (L R T: Q) (l: L ~> T) (r: R ~> T) + (B: @prepback Q L R T l r) : Type := { + has_umarrow : forall B0: Q, @has_medarrow Q L R T l r B B0 + * @medarrow_is_unique Q L R T l r B B0 + }. +#[short(type="pback"), verbose] +HB.structure Definition PBack (Q: precat) + {L R T : Q} (l: L ~> T) (r: R ~> T) := + { B of IsPBack Q L R T l r B }. + +(* packs all the definition together *) +HB.mixin Record IsPBack2 (Q: precat) (L R T: Q) (l: L ~> T) (r: R ~> T) + (B: @pspan Q L R T l r) : Type := { + comm_sq : comm_square l r (@lprj Q L R T l r B) rprj ; + has_umarrow : forall B0: Q, @has_medarrow Q L R T l r B B0 + * @medarrow_is_unique Q L R T l r B B0 + }. +#[short(type="pback2"), verbose] +HB.structure Definition PBack2 (Q: precat) + {L R T : Q} (l: L ~> T) (r: R ~> T) := + { B of IsPBack2 Q L R T l r B }. + + +(***********************************************************************) + +(*** CATEGORIES WITH PULLBACKS *) + +(* category with all pullbacks + This is not right, but shows the idea *) +HB.mixin Record HasPBKop C of Cat C := { + pbkop : forall {L R T: C} (l: L ~> T) (r: R ~> T), @pspan C L R T l r + }. +#[short(type="pbkop")] +HB.structure Definition PBKop := + {C of HasPBKop C & PreCat C }. + +#[wrapper] +HB.mixin Record HasPrePBKcat C of PBKop C : Type := { + is_gppbk : forall {L R T: C} (l: L ~> T) (r: R ~> T), + @IsPrePBack C L R T l r (@pbkop C L R T l r) + }. +#[short(type="prepbkcat")] +HB.structure Definition PrePBKcat := + {C of HasPrePBKcat C}. + +(* category with all pullbacks *) +(* PROBLEM: fails as a wrapper *) +(* #[wrapper] *) +HB.mixin Record HasPBKcat C of PrePBKcat C := { + is_gpbk : forall {L R T: C} (l: L ~> T) (r: R ~> T), + @IsPBack C L R T l r (@pbkop C L R T l r) + }. +#[short(type="pbkcat")] +HB.structure Definition PBKcat := + {C of HasPBKcat C & PreCat C }. + +(* on the other hand, this works... *) +#[wrapper] +HB.mixin Record HasPBK2cat C of PBKop C := { + is_gpbk2 : forall {L R T: C} (l: L ~> T) (r: R ~> T), + @IsPBack2 C L R T l r (@pbkop C L R T l r) + }. +#[short(type="pbk2cat")] +HB.structure Definition PBK2cat := + {C of HasPBK2cat C & PreCat C }. + + +(***********************************************************************) + +HB.mixin Record isInternalHom {C: quiver} (C0 : C) (C1 : obj C) := { + src : C1 ~> C0; tgt : C1 ~> C0 +}. +#[short(type="iHom")] +HB.structure Definition InternalHom {C: quiver} (C0 : C) := + { C1 of isInternalHom C C0 C1 }. + +Notation "X ':>' C" := (X : obj C) (at level 60, C at next level). + +Definition iprod_pb {C: pbk2cat} {C0 : C} (X Y : iHom C0) : + pspan (@tgt C C0 (X :> C)) (@src C C0 (Y :> C)) := + @pbkop C (X :> C) (Y :> C) C0 (tgt : (X :> C) ~> C0) (src : (Y :> C) ~> C0). + +(* could be problematic... *) +Program Definition iprod {C: pbk2cat} {C0 : obj C} (X Y : iHom C0) : C. +set (x := @iprod_pb C C0 X Y). +eapply x. +Defined. + +Notation "X *_ C0 Y" := (@iprod _ C0 (X : iHom C0) (Y : iHom C0)) + (at level 99, C0 at level 0, only parsing) : cat_scope. +Notation "X *_ C0 Y" := (@iprod _ C0 X Y) + (at level 99, C0 at level 0) : cat_scope. + + +(************************** END OF IT ********************) + + +(* +HB.mixin Record IsPBkObj {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) (B: Q) : Type := { + lprj : B ~> L ; + rprj : B ~> R + }. +#[short(type="pbkobj"), verbose] +HB.structure Definition PBkObj {Q: precat} + {L R T : Q} (l: L ~> T) (r: R ~> T) := + { B of IsPBkObj Q L R T l r B }. + +Definition comm_square {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) {B: Q} (p1: B ~> L) (p2: B ~> R) : Prop := + p1 \; l = p2 \; r. + +Definition comm_triangle {Q: precat} {A B C: Q} + (h: A ~> C) (f: A ~> B) (g: B ~> C) : Prop := + h = f \; g. + +HB.mixin Record IsMedArrow {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) + (P: forall (B: Q) (p1: B ~> L) (p2: B ~> R), Type) + {B: Q} (p1: B ~> L) (p2: B ~> R) {B0: Q} + (m: B0 ~> B) := { + marrow_prop : forall (p01: B0 ~> L) (p02: B0 ~> R), + P B0 p01 p02 -> comm_triangle p01 m p1 /\ comm_triangle p02 m p2 +}. +#[short(type="medarrow"), verbose] + HB.structure Definition MedArrow {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) + (P: forall (B: Q) (p1: B ~> L) (p2: B ~> R), Type) + {B: Q} (p1: B ~> L) (p2: B ~> R) (B0: Q) := { + m of @IsMedArrow Q L R T l r P B p1 p2 B0 m }. + +HB.tag +Definition has_medarrow {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) (B: @pbkobj Q L R T l r) := + forall B0, sigma m, forall p1 p2, + @MedArrow Q L R T l r (@comm_square Q L R T l r) B p1 p2 B0 m. + +#[wrapper] +HB.mixin Record HasMedArrow {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) + {B: Q} (p1: B ~> L) (p2: B ~> R) {B0: Q} := { + marrow : @has_medarrow Q L R T l r (@comm_square Q L R T l r) B p1 p2 B0 +}. + + +HB.tag +Definition has_medarrow {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) (B: @pbkobj Q L R T l r) := + forall B0, sigma m, forall p1 p2, + @MedArrow Q L R T l r (@comm_square Q L R T l r) B p1 p2 B0 m. + +Definition medarrow_unique {Q: precat} {L R T: Q} + (l: L ~> T) (r: R ~> T) + (P: forall (B: Q) (p1: B ~> L) (p2: B ~> R), Type) + {B: Q} (p1: B ~> L) (p2: B ~> R) {B0: Q} + (m m': medarrow l r P p1 p2 B0) : Prop := m = m'. + +HB.mixin Record IsPrePBack (Q: precat) (L R T: Q) (l: L ~> T) (r: R ~> T) + (B: @pbkobj Q L R T l r) : Type := { + comm_sq : comm_square l r (@lprj Q L R T l r B) rprj + }. +#[short(type="prepback"), verbose] +HB.structure Definition PrePBack (Q: precat) + {L R T : Q} (l: L ~> T) (r: R ~> T) := + { B of IsPrePBack Q L R T l r B }. + +#[wrapper] +HB.mixin Record IsPBack (Q: precat) (L R T: Q) (l: L ~> T) (r: R ~> T) + (B: @prepback Q L R T l r) : Type := { + marrow : @has_medarrow Q L R T l r B +}. + +HB.mixin unique_limit_prop {Q: precat} {L R T: Q} (l: L ~> T) (r: R ~> T) + (P: forall (B: Q) (p1: B ~> L) (p2: B ~> R), Type) + {B: Q} (p1: B ~> L) (p2: B ~> R) {B0: Q} (p01: B ~> L) (p02: B ~> R) : + Type := P B p1 p2 -> + forall B0 p01 p02, + P B0 p01 p02 -> + sigma (m: B0 ~> B), comm_triangle p01 m p1 /\ comm_triangle p02 m p2. + +Record isPBack (Q : precat) (L R T B : Q) : U := { + (p1: B ~> L) (p2: B ~> R) (l: L ~> T) (r: R ~> T) + (c : cospan A B) (s : span A B) := { + is_square : bot2left s \; left2top c = bot2right s \; right2top c; +}. + +HB.mixin Record isPBsquare (Q : precat) (L R T B : Q) + (p1: B ~> L) (p2: B ~> R) (l: L ~> T) (r: R ~> T) + (c : cospan A B) (s : span A B) := { + is_square : bot2left s \; left2top c = bot2right s \; right2top c; +}. +#[short(type=prepullback)] +HB.structure Definition PrePullback Q A B (c : cospan A B) := + {s of isPrePullback Q A B c s}. +Arguments prepullback {Q A B} c. +*) + diff --git a/structures.v b/theories/structures.v similarity index 92% rename from structures.v rename to theories/structures.v index 027c14427..e31781e98 100644 --- a/structures.v +++ b/theories/structures.v @@ -160,6 +160,18 @@ pred join o:classname, o:classname, o:classname. % in order to discover two mixins are the same) pred mixin-mem i:term, o:gref. +% [wrapper-mixin Wrapper NewSubject WrappedMixin] +% #[wrapper] HB.mixin Record hom_isMon T of Quiver T := +% { private : forall A B, isMon (@hom T A B) }. +% --> +% wrapper-mixin (indt "hom_isMon") (const "hom") (indt "isMon"). +pred wrapper-mixin o:mixinname, o:gref, o:mixinname. + +% designated identity function for wrapping (sometimes you don't have a +% structure op for it). +% [tag GR Class NParams] +pred tag o:gref, o:classname, o:int. + %%%%%% Memory of exported mixins (HB.structure) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Operations (named mixin fields) need to be exported exactly once, % but the same mixin can be used in many structure, hence this memory @@ -171,7 +183,9 @@ pred mixin-mem i:term, o:gref. % that contains the mixin M pred mixin-first-class o:mixinname, o:classname. -% memory of exported operations (TODO: document fiels) +% memory of exported operations. +% [exported-op Mixin MixinProjection Operation], where Operation is a +% structure projection. pred exported-op o:mixinname, o:constant, o:constant. % memory of factory sort coercion @@ -565,6 +579,29 @@ solve (goal _ _ Ty _ Args as G) GLS :- with-attributes (with-logging (std.do! [ Elpi Typecheck. Elpi Export HB.pack. +Elpi Tactic HB.from. +Elpi Accumulate Db hb.db. +Elpi Accumulate File "HB/common/stdpp.elpi". +Elpi Accumulate File "HB/common/database.elpi". +#[skip="8.1[56].*"] Elpi Accumulate File "HB/common/compat_acc_clauses_all.elpi". +#[only="8.1[56].*"] Elpi Accumulate File "HB/common/compat_acc_clauses_816.elpi". +Elpi Accumulate File "HB/common/utils.elpi". +Elpi Accumulate File "HB/common/log.elpi". +Elpi Accumulate File "HB/common/synthesis.elpi". +Elpi Accumulate File "HB/pack.elpi". +Elpi Accumulate lp:{{ + +solve (goal _ _ Ty _ Args as G) GLS :- with-attributes (with-logging (std.do! [ + pack.main-use-factories Ty Args Instance, + refine Instance G GLS, +])). + +}}. +Elpi Typecheck. + +Tactic Notation "HB.from" open_constr_list(L) := + elpi HB.from ltac_term_list:(L). + (* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *) (* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *) (* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *) @@ -640,7 +677,7 @@ main [const-decl N (some B) Arity] :- std.do! [ % compute the universe for the structure (default ) prod-last {coq.arity->term Arity} Ty, if (ground_term Ty) (Sort = Ty) (Sort = {{Type}}), sort Univ = Sort, - with-attributes (with-logging (structure.declare N B Univ)), + with-attributes (with-logging (with-unsafe-univ (structure.declare N B Univ))), ]. }}. @@ -664,6 +701,10 @@ actions N :- coq.env.current-library File, coq.elpi.accumulate current "export.db" (clause _ _ (module-to-export File E)), coq.elpi.accumulate current "export.db" (clause _ _ (module-to-export File O)), + + % hack + std.forall {std.iota 20} (x\begin-section "x",end-section), + if (get-option "mathcomp" tt ; get-option "mathcomp.axiom" _) (actions-compat N) true. pred actions-compat i:id. @@ -1188,6 +1229,69 @@ Elpi Export HB.check. (* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *) (* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *) +(** [HB.tag] declares a tag for mixin subjects + +[[ +HB.tag Definition N Params (x : S.type) : Type := x +]] + +*) + +#[arguments(raw)] Elpi Command HB.tag. +Elpi Accumulate Db hb.db. +Elpi Accumulate File "HB/common/stdpp.elpi". +Elpi Accumulate File "HB/common/database.elpi". +#[skip="8.1[56].*"] Elpi Accumulate File "HB/common/compat_acc_clauses_all.elpi". +#[only="8.1[56].*"] Elpi Accumulate File "HB/common/compat_acc_clauses_816.elpi". +Elpi Accumulate File "HB/common/utils.elpi". +Elpi Accumulate File "HB/common/log.elpi". +Elpi Accumulate File "HB/common/synthesis.elpi". +Elpi Accumulate File "HB/context.elpi". +Elpi Accumulate File "HB/instance.elpi". +Elpi Accumulate lp:{{ + +main [const-decl Name (some BodySkel) AritySkel] :- !, std.do! [ + std.assert-ok! (coq.elaborate-arity-skeleton AritySkel _ Arity) "HB: type illtyped", + coq.arity->nparams Arity N, + coq.arity->term Arity Ty, + std.assert-ok! (coq.elaborate-skeleton BodySkel Ty Body) "HB: body illtyped", + with-attributes (with-logging (std.do! [ + log.coq.env.add-const Name Body Ty @transparent! C, + coq.arity->implicits Arity CImpls, + if (coq.any-implicit? CImpls) + (@global! => coq.arguments.set-implicit (const C) [CImpls]) + true, + ])), + M is N - 1, + class-of-nth-arg M Ty Class, + acc-clause current (tag (const C) Class M), +]. +main [str G, str"|", int M] :- !, + coq.locate G GR, + coq.env.typeof GR Ty, + class-of-nth-arg M Ty Class, + acc-clause current (tag GR Class M). + +main _ :- coq.error "Usage: HB.tag Definition ... := T ...\nUsage: HB.tag | ". + +pred class-of-nth-arg i:int, i:term, o:classname. +class-of-nth-arg 0 (prod _ (global S) _\_) Class :- class-def (class Class S _). +class-of-nth-arg 0 (prod _ (app [global S|_]) _\_) Class :- class-def (class Class S _). +class-of-nth-arg N (prod Name Ty Bo) Class :- N > 0, !, M is N - 1, + @pi-decl Name Ty x\ class-of-nth-arg M (Bo x) Class. +class-of-nth-arg 0 T _ :- !, + coq.error "HB: the last parameter of a tag must be of a structure type:" {coq.term->string T}. +class-of-nth-arg _ T _ :- !, + coq.error "HB: not enough argsuments:" {coq.term->string T}. + +}}. +Elpi Typecheck. +Elpi Export HB.tag. + +(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *) +(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *) +(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *) + (** Technical notations from /Canonical Structures for the working Coq user/ *) Notation "`Error_cannot_unify: t1 'with' t2" := (unify t1 t2 None) (at level 0, format "`Error_cannot_unify: t1 'with' t2", only printing) :