There should be some principled way of dealing with "bare morphisms", which consist of the data of a morphism without the domain and codomain. Very often (i.e. acsets, lenses), we want to store this directly, because we don't want to redundantly store the domain.
One way to do this would be to have something like
struct DomCodomWrapper{Ob,Hom}
dom::Ob
codom::Ob
values::Hom
end
and then the function that you overload for composition looks like
compose(a::Ob, b::Ob, c::Ob, f::Hom, g::Hom)
This would allow us, for instance, to compose FinFunctions with
compose(_,_,_, f::Vector{Int}, g::Vector{Int}) = Int[g[j] for j in f]
More generally, this could be done for any GAT where the type constructors have arguments. But to start, doing this for categories would be hugely helpful.
There should be some principled way of dealing with "bare morphisms", which consist of the data of a morphism without the domain and codomain. Very often (i.e. acsets, lenses), we want to store this directly, because we don't want to redundantly store the domain.
One way to do this would be to have something like
and then the function that you overload for composition looks like
This would allow us, for instance, to compose FinFunctions with
More generally, this could be done for any GAT where the type constructors have arguments. But to start, doing this for categories would be hugely helpful.