Functor Picking

(very early draft)

Picking the Output

Imagine you need to come up with a program of type:

\[\begin{align} & = F \rightsquigarrow \text{Q} \end{align}\]

aka

\[\begin{align} & = \forall\ x\ . F\ x \rightarrow \text{Q}\ x \end{align}\]

Where, \(F\) is a fixed \(\text{Functor}\), but you get to pick \(\text{Q}\).

What different choices could you make, and what effect can they have?

There are some straight-forward choices…

Render the computation pointless with \(\text{Proxy}\):

\[\begin{align} & = F \rightsquigarrow \text{Proxy} \\ & = \forall\ x\ . F\ x \rightarrow \text{Unit} \\ & = \text{Unit} \end{align}\]

Select an \(x\) out of \(F\) with \(\text{Identity}\).

\[\begin{align} & = F \rightsquigarrow \text{Identity} \\ & = \forall\ x\ . F\ x \rightarrow \text{Identity}\ x \\ & = \forall\ x\ . F\ x \rightarrow x \end{align}\]

Refute \(F\) with \(\text{Const}\ \text{Void}\).

\[\begin{align} & = F \rightsquigarrow \text{Const}\ \text{Void} \\ & = \forall\ x\ . F\ x \rightarrow \text{Const}\ \text{Void}\ x \\ & = \forall\ x\ . F\ x \rightarrow \text{Void} \end{align}\]

Or, indeed, return whatever you like with \(\text{Const}\).

\[\begin{align} & = F \rightsquigarrow \text{Const}\ \text{KmettFanFiction} \end{align}\]

Implement two functions at once via a product (\(\text{_} \times \text{_}\)):

\[\begin{align} & = F \rightsquigarrow (\text{H} \times \text{G}) \\ & = \forall\ x\ . F\ x \rightarrow (\text{H} \times \text{G})\ x \\ & = \forall\ x\ . F\ x \rightarrow (\text{H}\ x \times \text{G}\ x) \\ & = (\forall\ x\ . F\ x \rightarrow \text{H}\ x) \times (\forall\ x\ . F\ x \rightarrow \text{G}\ x) \\ & = (F \rightsquigarrow \text{H}) \times (F \rightsquigarrow \text{G}) \end{align}\]

Add another input via \(\text{ReaderT}\):

\[\begin{align} & = F \rightsquigarrow \text{ReaderT}\ \text{Config}\ \text{H} \\ & = \forall\ x\ . F\ x \rightarrow \text{ReaderT}\ \text{Config}\ \text{H}\ x \\ & = \forall\ x\ . F\ x \rightarrow \text{Config} \rightarrow \text{H}\ x \\ & = \text{Config} \rightarrow \forall\ x\ . F\ x \rightarrow \text{H}\ x \\ & = \text{Config} \rightarrow F \rightsquigarrow \text{H} \end{align}\]

Tweaking this slightly we can introduce:

newtype (^) g f x = Exp (f x -> g x)

Then the new input can also refer to the quantification variable:

\[\begin{align} & = F \rightsquigarrow (\text{H} \mathrel{\hat{}} \text{G}) \\ & = \forall\ x\ . F\ x \rightarrow (\text{H} \mathrel{\hat{}} \text{G})\ x \\ & = \forall\ x\ . F\ x \rightarrow \text{G}\ x \rightarrow \text{H}\ x \\ & = \forall\ x\ . (F\ x \times \text{G}\ x) \rightarrow \text{H}\ x \\ & = \forall\ x\ . (F \times \text{G})\ x \rightarrow \text{H}\ x \\ & = (F \times \text{G}) \rightsquigarrow \text{H} \end{align}\]

Conveniently remember that the input isn’t just \(F\), it’s \(F \circ \text{G}\), via Ran by \(\text{G}\) (\(\text{_}/\text{G}\)):

\[\begin{align} & = F \rightsquigarrow (\text{H} / \text{G}) \\ & = \forall\ x\ . F\ x \rightarrow (\text{H} / \text{G})\ x \\ & = \forall\ x\ . F\ x \rightarrow (\forall\ y\ . (x \rightarrow \text{G}\ y) \rightarrow \text{H}\ y) \\ & = \forall\ x\ y\ . F\ x \rightarrow (x \rightarrow \text{G}\ y) \rightarrow \text{H}\ y \\ & = \forall\ y\ . (\exists\ x\ . (F\ x,\ x \rightarrow \text{G}\ y)) \rightarrow \text{H}\ y \\ & = \forall\ y\ . \text{Coyoneda}\ F\ (\text{G}\ y) \rightarrow \text{H}\ y \\ & = \forall\ y\ . F\ (\text{G}\ y) \rightarrow \text{H}\ y \\ & = \forall\ y\ . (F \circ \text{G})\ y \rightarrow \text{H}\ y \\ & = F \circ \text{G} \rightsquigarrow \text{H} \end{align}\]

Ah it’s actually an \(F\)-algebra on \(\text{C}\), via \(\text{Cont}\):

\[\begin{align} & = F \rightsquigarrow \text{Cont}\ \text{C} \\ & = \forall\ x\ . F\ x \rightarrow \text{Cont}\ \text{C}\ x \\ & = \forall\ x\ . F\ x \rightarrow (x \rightarrow \text{C}) \rightarrow \text{C} \\ & = (\exists\ x\ . (F\ x,\ x \rightarrow \text{C})) \rightarrow \text{C} \\ & = \text{Coyoneda}\ F\ \text{C} \rightarrow \text{C} \\ & = F\ \text{C} \rightarrow \text{C} \end{align}\]

Go mad and combine them in interesting ways:

\[\begin{align} & = F \rightsquigarrow ((\text{Cont}\ \text{A} / \text{B}) \times \text{ReaderT}\ \text{C}\ \text{D}) \\ & = (F\ (\text{B}\ \text{A}) \rightarrow \text{A}) \times (\text{C} \rightarrow F \rightsquigarrow \text{D}) \end{align}\]

Picking the Input

Now suppose things were the other way around, and instead of picking \(\text{Q}\) in:

\[\begin{align} & = F \rightsquigarrow \text{Q} \end{align}\]

We only get to pick the \(\text{F}\):

\[\begin{align} & = \text{F} \rightsquigarrow Q \end{align}\]

Like with products before, we can still implement multiple functions, but this time we’ll need to use coproducts (\(\text{_} + \text{_}\)):

\[\begin{align} & = (\text{G} + \text{H}) \rightsquigarrow Q \\ & = \forall\ x\ . (\text{G} + \text{H})\ x \rightarrow Q\ x \\ & = \forall\ x\ . (\text{G}\ x + \text{H}\ x) \rightarrow Q\ x \\ & = (\forall\ x\ . \text{G}\ x \rightarrow Q\ x) \times (\forall\ x\ . \text{H}\ x \rightarrow Q\ x) \\ & = (\text{G} \rightsquigarrow Q) \times (\text{H} \rightsquigarrow Q) \end{align}\]

As we previously saw when introducing (\(\text{_} \mathrel{\hat{}} \text{_}\)), we ended up with a product in the input. This time we can run the same scenaro backwards to end up with (\(\text{_} \mathrel{\hat{}} \text{_}\)) for the output.

\[\begin{align} & = (\text{F} \times \text{G}) \rightsquigarrow Q \\ & = \text{F} \rightsquigarrow (Q \mathrel{\hat{}} \text{G}) \\ & = \text{G} \rightsquigarrow (Q \mathrel{\hat{}} \text{F}) \\ & = \text{Proxy} \rightsquigarrow (Q \mathrel{\hat{}} (\text{F} \times \text{G})) \end{align}\]

Similarly to using Ran on the output to get a composition on the input, we can use Lan on the input to get a composition on the output:

\[\begin{align} & = (\text{G} \backslash \text{F}) \rightsquigarrow Q \\ & = \forall\ x\ . (\text{G} \backslash \text{F})\ x \rightarrow Q\ x \\ & = \forall\ x\ . (\exists\ y\ . (\text{F}\ y,\ \text{G}\ y \rightarrow x)) \rightarrow Q\ x \\ & = \forall\ x\ y\ . \text{F}\ y \rightarrow (\text{G}\ y \rightarrow x) \rightarrow Q\ x \\ & = \forall\ y\ . \text{F}\ y \rightarrow \forall\ x\ . (\text{G}\ y \rightarrow x) \rightarrow Q\ x \\ & = \forall\ y\ . \text{F}\ y \rightarrow Q\ (\text{G}\ y) \\ & = \forall\ y\ . \text{F}\ y \rightarrow (Q \circ \text{G})\ y \\ & = \text{F} \rightsquigarrow (Q \circ \text{G}) \end{align}\]

Updated: