Functor definition in category theory

Are you asking for something like this? I know there is the tikz-cd package explicitly for commutative diagrams, but you mentioned you would like to avoid the tikz apparatus.

\documentclass[12pt]{article}
\usepackage[usestackEOL]{stackengine}
\usepackage{mathtools,amssymb}
\newcommand\functor[1][l]{\csname#1functor\endcsname}
\newcommand\lfunctor[3]{%
  \setbox0=\hbox{$#2$}%
  \kern\wd0%
  \ensurestackMath{\Centerstack[c]{#1\\ \mathllap{#2\;\,}\mathclap{\DownArrow}\\#3}}%
}
\newcommand\rfunctor[3]{%
  \setbox0=\hbox{$#2$}%
  \ensurestackMath{\Centerstack[c]{#1\\\mathclap{\DownArrow}\mathrlap{\,\;#2}\\#3}}%
  \kern\wd0%
}
\newcommand\functormapsto{\mathrel{\ensurestackMath{\Centerstack[c]{\longmapsto\\ \\\longmapsto}}}}
\setstackgap{L}{1.3\normalbaselineskip}
\newcommand\DownArrow{\rotatebox[origin=c]{-90}{$\longrightarrow$\,}}
\begin{document}
\[
\functor[l]{a}{f}{b}
\functormapsto
\functor[r]{F_a}{F_f}{F_b}
\]
\end{document}

enter image description here


I'd go with tikz-cd and a key value interface:

\documentclass{article}
\usepackage{xparse,tikz-cd}

\ExplSyntaxOn

\NewDocumentCommand{\functor}{O{}m}
 {
  \group_begin:
  \keys_set:nn { nicolas/functor } { #2 }
  \nicolas_functor:n { #1 }
  \group_end:
 }

\keys_define:nn { nicolas/functor }
 {
  domain   .tl_set:N = \l_nicolas_functor_domain_tl,
  codomain .tl_set:N = \l_nicolas_functor_codomain_tl,
  name     .tl_set:N = \l_nicolas_functor_name_tl,
  source   .tl_set:N = \l_nicolas_functor_source_tl,
  target   .tl_set:N = \l_nicolas_functor_target_tl,
  map      .tl_set:N = \l_nicolas_functor_map_tl,

  name   .initial:n = F,
  source .initial:n = a,
  target .initial:n = b,
  map    .initial:n = f,
 }

\dim_new:N \g_nicolas_functor_space_dim

\cs_new:Nn \nicolas_functor:n
 {
  \begin{tikzcd}[ampersand~replacement=\&,#1]
  \dim_gset:Nn \g_nicolas_functor_space_dim { \pgfmatrixrowsep }
  \l_nicolas_functor_domain_tl
  \arrow[r,"\l_nicolas_functor_name_tl"] \&
  \l_nicolas_functor_codomain_tl
  \\[\dim_eval:n {1ex-\g_nicolas_functor_space_dim}]
  \l_nicolas_functor_source_tl
  \arrow[r,mapsto] \arrow[d,swap,"\l_nicolas_functor_map_tl"] \&
  \l_nicolas_functor_name_tl \l_nicolas_functor_source_tl
  \arrow[d,"\l_nicolas_functor_name_tl \l_nicolas_functor_map_tl"]
  \\
  \l_nicolas_functor_target_tl
  \arrow[r,mapsto] \&
  \l_nicolas_functor_name_tl \l_nicolas_functor_target_tl
  \end{tikzcd}
 }
\ExplSyntaxOff

\begin{document}

\functor{
  domain=X,
  codomain=Y,
}

\bigskip

\functor{
  domain=\mathbf{Ring},
  codomain=\mathbf{Set},
  name=U,
  source=R,
  target=S,
}

\bigskip

\functor[row sep=huge]{
  domain=\mathbf{Ring},
  codomain=\mathbf{Set},
  name=U,
  source=R,
  map=\varphi,
  target=S,
}

\end{document}

In the optional argument you can pass tikz-cd options; the key names should be clear from the examples.

enter image description here