TL;DR: Is there a method of constructing morphisms in a cartesian closed category that is just as simple as constructing functions between types?
Hi,
I'm working on defining Mealy machines (a type of automata) in a general way. Mealy machines can be defined in any monoidal category, and I'm particularly interested in defining them in the category Preord of preorders.
For instance, in the category of types, we have this definition of a Mealy machine:
Given a mealy machine Mealy α β, we get an induced mealy machine which takes a non-empty list of inputs (modeled as α × List α) and gives an output in β:
As we can see, we have replaced the types and functions with preorders and monotone functions. Note that we are using the uncurried form of trans and out. I also tried doing the curried version, but then I had to do a lot of currying/uncurrying with curry.symm.toFun and curry.toFun everywhere.
Now, let's define iteration of a PreordMealy:
openListopenOrderHomdeffoldrHom'[Preorderα][Preorderβ](f:α×β→oβ):β×Listα→oβwheretoFun:=(foldrf.toFun.curry).uncurrymonotone':=sorrydeffoldrHom[Preorderα][Preorderβ](f:α×β→oβ):Listα×β→oβ:=(foldrHom'f).comp(OrderHomClass.toOrderHomOrderIso.prodComm)--(I couln't find the following definition in mathlib)defprodAssoc[Preorderα][Preorderβ][Preorderγ]:(α×β)×γ≃o(α×β×γ)wheretoEquiv:=Equiv.prodAssocαβγmap_rel_iff':=byaesopdefMealy.iterate(m:Mealyαβ):Mealy(Preord.of$(α×Listα))βwherestate:=m.statetrans:=m.trans.comp((prodMapid(foldrHomm.trans)).comp(OrderHomClass.toOrderHomprodAssoc))out:=m.out.comp((prodMapid(foldrHomm.trans)).comp(OrderHomClass.toOrderHomprodAssoc))
As you can see, this is a lot more verbose than the version for types. The curried version is even worse (I will spare you the details).
My question is: Is there a simpler way to define the monotone functions above, preferably in the curried version (trans : α →o state →o state and out : α →o state →o β)?
In theory, it should be just as simple as in the case of types, given the fact that Preord is a cartesian closed category, so it should allow lambda notation.
My question is: Is there a simpler way to define the monotone functions above, preferably in the curried version (trans : α →o state →o state and out : α →o state →o β)?
In theory, it should be just as simple as in the case of types, given the fact that Preord is a cartesian closed category, so it should allow lambda notation.
Probably, there is, just no one has implemented such a thing yet.
Our approaches are a bit different. While your approch seems to be using macros for everything, my approach tries to reuse as much of the standard syntax as possible.
Currently I'm trying to get rid of the macros, and the need to use pair in my prototype, fully relying on coercion. For instance, one should be able to just write code like this:
I'm trying to use coercion to apply morphisms as f x, but I'm struggling to get the coercions to fire. Here is the code:
importMathlib.CategoryTheory.ChosenFiniteProductsopenCategoryTheoryMonoidalCategoryvariable[CategoryC][ChosenFiniteProductsC]variable{rabc:C}defPort(ra:C):=r⟶adefencode{ab:C}(f:a⟶b):Portra→Portrb:=(·≫f)instance:CoeFun(a⟶b)(fun_=>∀{r},Portra→Portrb):=⟨funf=>encodef⟩defpair:Portra×Portrb->Portr(a⊗b):=ChosenFiniteProducts.lift.uncurry@[default_instance]instance:CoeOut(Portra)(Portra):=⟨id⟩@[default_instance]instance[CoeOutA(Portra)][CoeOutB(Portrb)]:CoeOut(A×B)(Portr(a⊗b)):=⟨pair∘Prod.mapCoeOut.coeCoeOut.coe⟩variable{f:a⊗b⟶c}variable{x:Portra×Portrb}-- I want to use coersions to be able to write `f x` and get a value of type `Port r c`.-- This works:#checkf(CoeOut.coex)-- (fun {r} => encode f) (CoeOut.coe x) : Port r c#checkf(x:Portr(a⊗b))-- (fun {r} => encode f) ((pair ∘ Prod.map id id) x) : Port r c#check(fx:Portrc)-- (fun {r} => encode f) ((pair ∘ Prod.map id id) x) : Port r c-- This coercion gives an error:#checkfx-- application type mismatch-- (fun {r} => encode f) x-- argument-- x-- has type-- Port r a × Port r b : Type ?u.50444-- but is expected to have type-- Port ?m.56807 (a ⊗ b) : Type ?u.50444