Two weeks ago I wrote about `Overloaded:Categories`

, and mentioned two brief examples. In this post I will walk through a more complete example. The topic is bitonic sorters.

Such domain "networks with N-inputs and M-outputs" are unfairly well suited for category representation. But first let me show few pictures^{1}. We'll see how this pictures are drawn from the same code as computation. The horizontal lines represent signals. The vertical lines represent compare-and-swap operator. I.e. for this two inputs we apply a function

```
cas :: Ord a => (a,a) -> (a,a)
= if x < y then (x,y) else (y,x) cas (x,y)
```

For four inputs:

Eight inputs:

Or sixteen inputs:

In the last network, there are 80 comparators. The network is not optimal, there is known network using just 60 comparators, you can find its diagram in *The Art Of Computer Programming*. Knuth also explains how bitonic sort networks are constructed i.e. why they work.

I should immediately point out that this wouldn't be doable with arrows, as the categories have `Functor`

s as objects i.e. type constructors of kind `Type -> Type`

, not just `Type`

s.

Lets define a super-concise names for well-known functors. We will see soon why this is a good idea.

```
newtype I a = I a -- Identity
data U a = U -- Proxy
data (f :*: g) a = f a :*: g a -- Product
```

Next we define one useful example category type:

`newtype A x f g = A { runA :: f x -> g x }`

Note, this is not a natural transformation, as the `x`

argument is not closed over (no `RankNTypes`

). We'll need it "outside", so we can require `Ord x`

needed for sorting. The type argument is unorthodox, but this way it fits into `Category`

class. The `A x`

instances resemble the `(->)`

instances:

```
instance Category (A x) where
id = A id
A f . A g = A (f . g)
instance CategoryWith1 (A x) where
type Terminal (A x) = U
= A (\_ -> U)
terminal
instance CartesianCategory (A x) where
type Product (A x) = (:*:)
= A (\(x :*: _) -> x)
proj1 = A (\(_ :*: y) -> y)
proj2
A f) (A g) = A (\x -> f x :*: g x) fanout (
```

We also define a new ad-hoc type-class, `SortingNetwork`

. It basically says that sorting networks are cartesian categories, where the categorical product is the functor product `:*:`

. The `block`

operator is used to place wires on the diagrams, otherwise it does nothing.

```
class (CartesianCategory cat, Product cat ~ (:*:))
=> SortingNetwork cat
where
block :: cat a b -> cat a b
= id block
```

Bitonic sorter networks are defined recursively. We'll use Haskell's type-class machinery to synthesize them for us. Before we can dive into actual sorter, we need two helper primitives:

```
class Pairwise f g where
pairwise :: SortingNetwork cat
=> cat (I :*: I) (I :*: I)
-> cat (f :*: g) (f :*: g)
class Opposite f g where
opposite :: SortingNetwork cat
=> cat (I :*: I) (I :*: I)
-> cat (f :*: g) (f :*: g)
```

These primitives are quite similar. Given some primitive two-wire function (like compare-and-swap), the `pairwise`

connects wires in two blocks in order:

and `opposite`

connects them in opposite order:

Both operations are parallel if the "hardware" supports it. (Unfortunately we cannot take advantage of that in Haskell, at least easily).

The instances are simple to define. The base case is `I I`

. Then we can return the primitive function directly:

```
instance Pairwise I I where
= id pairwise
```

The induction case is for product `:*:`

. We require that halves of product can be connected pairwise. Because of this definition we essentially can make only networks with size . That is not a real issue, as we will see later.

The instance definition is *easy* using `Overloaded:Categories`

. Manual definition wouldn't be as pretty:

```
instance (Pairwise x u, Pairwise y v) => Pairwise (x :*: y) (u :*: v) where
= proc ((x,y), (u,v)) -> do
pairwise f <- pairwise f -< (x,u)
(x',u') <- pairwise f -< (y,v)
(y',v') -< ((x',y'), (u',v')) identity
```

The `Opposite`

instances are defined similarly.

If you have already examined the bitonic sorter networks, you noticed that they are composed from smaller `Pairwise`

and `Opposite`

blocks. So this is all we need to define bitonic sorter networks.

Bitonic sorter is kind-of merge-sort. First we sort the two halves, and then we merge them. Thus the type-class for them has two methods:

```
class BitonicSort f where
bitonicSort :: SortingNetwork cat
=> cat (I :*: I) (I :*: I)
-> cat f f
bitonicMerge :: SortingNetwork cat
=> cat (I :*: I) (I :*: I)
-> cat f f
```

The base case for `I`

is easy. With only one wire there is nothing to sort:

```
instance BitonicSort I where
= identity
bitonicSort _ = identity bitonicMerge _
```

The induction step shows the structure.

The sort is recursive:

- sort the halves
- cas the opposites
- merge the halves.

The merge is also recursive:

- cas pairwise
- merge the halves.

```
instance (Pairwise f g, Opposite f g, BitonicSort f, BitonicSort g)
=> BitonicSort (f :*: g)
where
=
bitonicSort cas *** bitonicSort cas) >>>
block (bitonicSort cas >>>
block (opposite cas) *** bitonicMerge cas)
block (bitonicMerge cas
=
bitonicMerge cas >>>
block (pairwise cas) *** bitonicMerge cas)
block (bitonicMerge cas
(***) :: CartesianCategory cat
=> cat a b -> cat c d -> cat (Product cat a c) (Product cat b d)
*** g = fanout (proj1 >>> f) (proj2 >>> g) f
```

Here I haven't used `Overloaded:Categories`

, as it doesn't offer much help. Here *point-free* approach is clearer.

As we have have networks defined for all sufficient categories, we can use the already define concrete instance `A x`

. We simply need to instantiate `bitonicSort`

, with a primitive compare-and-swap element:

```
cas :: A a (I :*: I) (I :*: I)
= A $ \(I x :*: I y) ->
cas if x <= y
then I x :*: I y
else I y :*: I x
```

Then the sort is just plumbing of data constructors. To avoid using tuples in the result I define function in continuation passing style.

```
sort4 :: Ord a
=> a -> a -> a -> a
-> (a -> a -> a -> a -> r)
-> r
=
sort4 a b c d kont let input = (I a :*: I b ) :*: (I c :*: I d)
I a' :*: I b') :*: (I c' :*: I d') = runA (bitonicSort cas) input
(
in kont a' b' c' d'
```

We can `QuickCheck`

this function:

```
$ \a b c d ->
quickCheck $ \a' b' c' d' ->
sort4 a b c d sort [a,b,c,d] === [a',b',c',d' :: Int]
```

It works perfectly.

Below is the Core for `sort4`

. There are no allocations, just `jump`

s around (and six compare-and-swaps as in the diagram). There are few casts as types of some continuations are mentioning `I`

. The `:*:`

constructors are however gone. (I was positively surprised how well GHC does job here).

```
$workerSort4
$workerSort4
= \ @ a
@ r
lessEqual
x1 x2 x3 x4->
kont
join {$kont1 y1 y2
= join {
$kont2 z1 z2 z3 z4
= join {
$kont3 w1 w2 w3 w4
= join {
$kont4 q1 q2
= case lessEqual (w2 `cast` <Co:2>) (w4 `cast` <Co:2>)
of {
False ->
kont`cast` <Co:2>)
(q1 `cast` <Co:2>)
(q2 `cast` <Co:2>)
(w4 `cast` <Co:2>);
(w2 True ->
kont`cast` <Co:2>)
(q1 `cast` <Co:2>)
(q2 `cast` <Co:2>)
(w2 `cast` <Co:2>)
(w4 in
} } case lessEqual (w3 `cast` <Co:2>) (w1 `cast` <Co:2>) of {
False -> jump $kont4 w1 w3;
True -> jump $kont4 w3 w1
in
} } case lessEqual (z1 `cast` <Co:2>) (z4 `cast` <Co:2>) of {
False ->
case lessEqual (z2 `cast` <Co:2>) (z3 `cast` <Co:2>) of {
False -> jump $kont3 z3 z2 z4 z1;
True -> jump $kont3 z2 z3 z4 z1
};True ->
case lessEqual (z2 `cast` <Co:2>) (z3 `cast` <Co:2>) of {
False -> jump $kont3 z3 z2 z1 z4;
True -> jump $kont3 z2 z3 z1 z4
}in
} } case lessEqual x3 x4 of {
False -> jump $kont2 y1 y2 (x4 `cast` <Co:3>) (x3 `cast` <Co:3>);
True -> jump $kont2 y1 y2 (x3 `cast` <Co:3>) (x4 `cast` <Co:3>)
in
} } case lessEqual x1 x2 of {
False -> jump $kont1 (x2 `cast` <Co:3>) (x1 `cast` <Co:3>);
True -> jump $kont1 (x1 `cast` <Co:3>) (x2 `cast` <Co:3>)
}
```

It's great that GHC optimises the above example. But will it do as great job for network of 16 inputs? You don't know, untill you try and inspect the produced Core.

There is a way to be sure, by constructing good code: *Template Haskell*. The commonly used Template Haskell is untyped and error prone, but there is also *Typed Template Haskell* variant. It is quite simple (to the first approximation). Instead of single delimiters like `[| Just $x |] :: ExpQ`

, we use double delimiters:

`|| Just $$x ||] :: TExpQ (Maybe Int) -- if x :: TExpQ Int [`

There is one trick to know. Instead of direct result returning as we had with `A x`

we need to use continuation-passing-style.

```
type Code a = TExpQ a
newtype Staged x f g = St
runStaged :: forall r. f (Code x) -> (g (Code x) -> Code r) -> Code r } {
```

Rewriting `Category`

and `CartesianCategory`

instances is an easy exercise. But why we need CPS? That can be illustrated by an implementation of `cas`

.

```
cas :: Code (a -> a -> Bool) -> Staged a (I :*: I) (I :*: I)
= St $ \(I x :*: I y) kont ->
cas le || let joinP a b = $$(kont (I [|| a ||] :*: I [|| b ||]))
[in
if $$le $$x $$y
then joinP $$x $$y
else joinP $$y $$x
||]
```

The continuation provides the code "which will happen later", so we can generate `let`

(which is recognized as a join point). If we used direct style, there wouldn't be a way to generate code like that.

Notice that we pass comparator as `Code (a -> a -> Bool)`

. This is because currently TTH doesn't work well with type-class methods. This is a workaround.

With `cas`

done and `Staged`

having category instances we can instantiate `bitonicSort`

. This code is the same as with non-TH version previously.

```
sort4code :: Code (a -> a -> Bool)
-> Code a -> Code a -> Code a -> Code a
-> (Code a -> Code a -> Code a -> Code a -> Code r)
-> Code r
=
sort4code le a b c d kont let input = (I a :*: I b ) :*: (I c :*: I d)
in runStaged (bitonicSort $ cas le) input $
I a' :*: I b') :*: (I c' :*: I d')) ->
\(( kont a' b' c' d'
```

And then we can use it. We *generate* the sorting code using local names bound by `sort4`

definition:

```
sort4 :: (a -> a -> Bool)
-> a -> a -> a -> a
-> (a -> a -> a -> a -> r)
-> r
=
sort4 le a b c d kont $$(sort4code [|| le ||] [|| a ||] [|| b ||] [|| c ||] [|| d ||] $
-> [|| kont $$a' $$b' $$c' $$d' ||]
\a' b' c' d' )
```

We can examine first what we generate, using `-ddump-splices`

(The names are cleaned up):

```
=
lessThan x1 x2 x3 x4 kont let
joinP0 y1 y2= let
joinP1 y3 y4= let
joinP2 z1 z2= let
joinP3 z3 z4= let
joinP4 w1 w2= let
joinP5 w3 w4= kont w1 w2 w3 w4
in
if lessThan z4 z2 then
joinP5 z4 z2else
joinP5 z2 z4in
if lessThan z1 z3 then
joinP4 z1 z3else
joinP4 z3 z1in
if lessThan y2 y3 then
joinP3 y2 y3else
joinP3 y3 y2in
if lessThan y1 y4 then
joinP2 y1 y4else
joinP2 y4 y1in
if lessThan x3 x4 then
joinP1 x3 x4else
joinP1 x4 x3in
if lessThan x1 x2 then
joinP0 x1 x2else
joinP0 x2 x1
```

It looks very nice. The GHC correctly recognizes the jump points, otherwise the generated Core (with `-ddump-simpl`

) is essentially the same. There weren't left much for GHC to do. The produced Core is similar to the variant GHC optimised from direct definition, except this one is more regular (I'm not sure why the Core above is slightly irregular). But most importantly, we know we will get this good result using staged programming / TTH as it is constructed explicitly. We are not relying on compiler being sufficiently smart, we tell it what to do.

It's good to have smart compiler, but in some specific use-cases general compiler general heuristics might not be well suited or enough. In particular, one might want to use even exponential-time optimization routine in some specific case, but no-one would like that used for everything.

```
sort4= \ @ a_ad1P
@ r_ad1Q
lessThan
x1 x2 x3 x4->
kont let {
joinP0= \ y1 y2 ->
let {
joinP1= \ y3 y4 ->
let {
joinP2= \ z1 z2 ->
let {
joinP3= \ z3 z4 ->
let {
joinP4= \ w1 w2 ->
let {
joinP5= \ w3 w4 ->
kont w1 w2 w3 w4in
} case lessThan z4 z2 of {
False -> joinP5 z2 z4;
True -> joinP5 z4 z2
in
} } case lessThan z1 z3 of {
False -> joinP4 z3 z1;
True -> joinP4 z1 z3
in
} } case lessThan y2 y3 of {
False -> joinP3 y3 y2;
True -> joinP3 y2 y3
in
} } case lessThan y1 y4 of {
False -> joinP2 y4 y1;
True -> joinP2 y1 y4
in
} } case lessThan x3 x4 of {
False -> joinP1 x4 x3;
True -> joinP1 x3 x4
in
} } case lessThan x1 x2 of {
False -> joinP0 x2 x1;
True -> joinP0 x1 x2
}
```

Another important observation is that we didn't need to touch `bitonicSort`

definition. We only created a new instance of `Category`

with a `cas`

primitive. Then the code was generated for us (truly at compile time).

The diagram drawing code is yet another instantiation. The type I used is quite simple:

```
newtype Diagram f g =
D { runD :: forall r. f Int -> (g Int -> [Piece] -> r) -> r }
data Piece = CAS Int Int
| Pieces [Piece]
```

We provide `f`

with distinct integers for each wire, and at the end we'll get which one are compared (and in the proper order). The `block`

operator of `SortingNetwork`

will create `Pieces`

, so we get more nicely aligned diagrams.

There is also a neat trick for generating the initial wire numbers. Recall that we used three `Functor`

s. They are also `Traversable`

and `Applicative`

. Thus we can generate initial `f Int`

using a traversal with `State`

, or more conveniently using `mapAccumL`

.

```
input :: (Applicative f, Traversable f) => f Int
= snd $ mapAccumL (\s () -> (s + 1 ,s)) 0 (pure ()) input
```

So far we have been limited to networks of size. We can get all other networks by simply omitting top or bottom wires, treating them as *always smaller* or *always bigger* values. This is the second reason why we bothered with Functor kind. First one is that staging example wouldn't been possible either.^{2}

For example if we need a sorting network of six inputs, we can instantiate it for a functor

`type Six = ((U :*: I) :*: (I :*: I)) :*: ((I :*: I) :*: (I :*: U)) `

The resulting network is a truncated version of the eight network:

This network has 13 comparators (optimal has 12). Not bad.

Programming with categories is fun. They offer inspectable static-shape computation as does `Applicative`

s, but they have quite different ergonomics.

Where `Applicative`

concentrates on "the objects", category (or `Arrow`

) approach is concentrated on "the arrows". Which one suits your particular domain depends. Categories work very well for sorting networks, sorting network is "an arrow", not the end result. I have hard time imagining how this can be represented with `Applicative`

s.

We defined a *bitonic sort* using categories (with a little help of `Overloaded:Categories`

), which we than instantiated three times:

- We interpreted the code directly
- Used Typed Template Haskell to generate more optimal code
- And lastly we drew diagrams from the same definitions.

We can (and maybe should) to continue and add an optimization layer - even the simple - one. If we further remove a wire from six-network above we will get a network with a redundant comparator. I leave the implementation of an optimizer as a tough but fun and rewarding exercise for a reader ;)

*Hints:* The optimizer usage looks like:

```
sort5optDiagram :: Diagram Five Five
= runOptimize $
sort5optDiagram >>>
bitonicSort (optimizedCas cas) bitonicSort (optimizedCas cas)
```

Also https://www.well-typed.com/blog/2014/12/simple-smt-solver/ and and zero-one principle may be useful.

So even we sort twice, we get only nine comparator network:

*Acknowledgments* I want to thank Andres Löh for introducing me to Typed Template Haskell, and Matthew Pickering for working on it in GHC.

The `Overloaded:Unit`

is the third and the last of the new features of recent overloaded 0.2.1 release. I wrote about `Overloaded:Categories`

, `Overloaded:Do`

previously. `overloaded`

package uses source plugins to reinterpret syntax in different ways.

`Overloaded:Unit`

is (hopefully) clearly a tongue-in-cheek feature. What we can do? We can overload what `()`

means.

Without any overloading we have `() :: ()`

. With `{-# OPTIONS_GHC -fplugin=Overloaded #-}`

we can make that symbol anything.

The most sensible overloading is into boring. You can specify that by

```
{-# OPTIONS_GHC -fplugin=Overloaded
-fplugin-opt=Overloaded:Unit=Data.Boring.boring #-}
```

What is `boring`

? Haddock tell us. There is also a law.

```
-- | 'Boring' types which contains one thing, also
-- 'boring'. There is nothing interesting to be gained by
-- comparing one element of the boring type with another,
-- because there is nothing to learn about an element of the
-- boring type by giving it any of your attention.
--
-- /Boring Law:/
--
-- @
-- 'boring' == x
-- @
--
class Boring a where
boring :: a
```

The above is a "proper implementation" of Conor McBride StackOverflow answer to What does () mean in Haskell -question

The answer starts with

() means "Boring".

So don't blame me for `Overloaded:Unit`

, it wasn't my idea :)

The `overloaded`

library by default makes `()`

mean `nil`

. Lispers may agree with that choice.

Another choice is to make `()`

mean `def`

from lawless `Defaul`

t type class.

As `def`

is used as ad-hoc value for default options, we could write

`& axis_line_style . line_width .~ 2 () `

or

```
= 2
() { _line_width = red
, _line_color }
```

Is that a good idea? Who am I to judge!

When you work with compiler internals, or more generally into implementation of some specification, you often enough learn stuff you didn't think about. Formalization makes corner cases more visible.

One example is:

```
Prelude> ( )
()
```

Try in your GHCi prompt if you don't believe me.

This leads to a question: Why unit have been given special syntax in the first place? Why could we had

`data Unit = Unit`

Then there would been a StackOverflow question for Conor to answer! And we could use `boring`

, `def`

or `Unit`

. Those would be "overloadable" with custom preludes, i.e. basic language feature: swapping imports.

We can think about `()`

as 0-tuple. But the syntax is not consistent:

```
-- 0-tuple i.e. unit
() -- just x i.e. NOT 1-tuple
(x) -- 2-tuple i.e. pair
(x,y) -- 3-tuple i.e. triple (x,y,z)
```

Yet, there is 1-tuple in GHC. Kind-of.

```
Prelude Language.Haskell.TH> let x = 'x'
x :: Char
Prelude Language.Haskell.TH> print $( conE (tupleDataName 1) `appE` [| x |] )
<interactive>:12:7: error:
Exception when trying to run compile-time code:
• 1
tupleDataName CallStack (from HasCallStack):
error, called at libraries/template-haskell/Language/Haskell/TH/Syntax.hs:1236:19 in template-haskell:Language.Haskell.TH.Syntax
Code: conE (tupleDataName 1) `appE` [| x |]
In the untyped splice: $(conE (tupleDataName 1) `appE` [| x |]) •
```

I haven't tried to that using GHC internals, whether one will generate panics by creating 1-tuples (i.e. boxes), or whether it will "just work".

`data Box a = Box a`

is valid data-type - and sometimes even useful. We cannot use 1-tuple for it - because there isn't syntax for one, yet we have `()`

for 0-tuple. Such inconsistencies.

We need *some syntax* for tuples however. The parenthesis delimit where tuple starts and ends. The `(1, 'x', "foo")`

is clearly a triple. Without parenthesis `1, 'x', "foo"`

would be ambiguous, that could be either triple or nested pairs - three options! One could use and to delimit tuples leaving `(`

and `)`

only for grouping. But using Unicode for something as central as tuples is not a good idea. So overloading parenthesis is probably the least bad option. But not great.

The very evil interview-question would be to ask to list all the ways the dot is overloaded (or will be overloaded) in GHC Haskell. The will be are Local Do and RecordDotSyntax proposals, but we have plenty already. Poor dot, stretched for about everything. **Hot take**: *Disallow . as an operator, making it a punctuation, like comma or semicolon.* It feels it would be easier to come up with new function composition operator, than try to disambiguate ever-increasing dot usage.

`TupleSections`

. I don't know how divided community is about these. I think that `(left,)`

and `(,right)`

sections are somewhat ok, even I avoid them. The `(,)`

is kind-of an infix operator (which it isn't).

Triples and bigger tuples on the other hand...

`"foo",,,True) :: b -> c -> ([Char], b, c, Bool) (`

for me this looks like syntax error.

But on the other hand, if you are ok with that syntax, it definitely should be overloadable for arbitrary data-types, why stop with tuples.

```
data Foo = Foo String Int Char Bool deriving (Generic, ...)
"foo",,,True) :: Char -> Bool -> Foo (
```

Wouldn't that be awesome? Stay tuned for `Overloaded:TupleSections`

.

I’m a weird person. I like writing . With all of its downsides, it’s quite flexible.

This blog post is written in `tex`

file, not markdown. With the help of `latex-svg`

, the included math and some *other* environments work. We are still constrained by what pandoc supports, but there is a lot.

Let us write few examples of what we can do.

Formulas

or

work nicely.

As `pandoc`

can preserve raw latex blocks and `latex-svg`

renders them, you can draw `tikzcd`

diagrams:

Writing tables in markdown is a pain. It is painful in also but less.

foo | bar | quu |
---|---|---|

foo1 | 2345678 | quu9 |

foo123 | 456 | quu789 |

`pandoc`

recognizes `code`

environment. So we get code highlighting!

```
fact :: Integer -> Integer
= product [2 .. n] fact n
```

The benefit of writing posts in is that you can convert to PDF. You can also start with markdown, and use pandoc to convert it to tex document, and that is what more reasonable people do.

]]>The `Overloaded:Categories`

is another of the new features of recent overloaded 0.2.1 release. I wrote about `Overloaded:Do`

, last week `overloaded`

package uses source plugins to reinterpret syntax in different ways.

Alexis King (lexi-lambda) is working on various Arrows issues, including Constrained based arrow notation -ghc-proposal. `Overloaded:Categories`

is however orthogonal. We are not considered as much with *how* arrow notation is desugared, but rather into what.

My claim is that `Arrow`

-classes are maybe not what we want to desugar into. Samuel Gélineau (gelisam) works on Template Haskell library `category-syntax`

to desugar `do`

notation into category classes. `Overloaded:Categories`

is different as it desugars arrow notation using source plugin functionality.

We'll discuss `Arrow`

class and its alternative `CartesianCategory`

, how we can desugar into latter, and see few examples of `Overloaded:Categories`

where GHC `Arrows`

are not applicable.

This work and especially AD example are inspired by Conal Elliott Compiling to categories.

Let us revisit `Arrow`

type-class. The most minimal definition is

```
class Category a => Arrow a where
arr :: (b -> c) -> a b c
(***) :: a b c -> a b' c' -> a (b,b') (c,c')
```

The first problem is the `arr`

combinator. The arrow notation desugaring doesn't need as powerful combinator. `arr`

is used to do data-plumbing, rearranging tuple fields, in other words:

```
proj1 :: a (b,c) b
proj2 :: a (b,c) c
(&&&) :: a b c -> a b c' -> a b (c,c')
-- or
dup :: a b c -> a b (c,c)
```

would be enough!

We *can* rather desugar into category theory inspired class

```
class Category a => CartesianCategory a where
proj1 :: a (b, c) b
proj2 :: a (b, c) c
(&&&) :: a b c -> a b c' -> a b (c, c')
```

A somewhat natural generalization is to not require **product** object to be a pair. This allows `CartesianCategory`

to be **polykinded**.

```
class Category a => CartesianCategory (a :: k -> k -> Type) where
type Product a :: k -> k -> k
proj1 :: a (Product a b c) b
proj2 :: a (Product a b c) c
(&&&) :: a b c -> a b c' -> a b (Product a c c')
-- ^ called 'fanout' in the Overloaded.Categories
```

`Arrow`

is more powerful than `CartesianCategory`

. We can write `CartesianCategory`

instance for `WrappedArrow`

:

```
newtype WrappedArrow arr b c = WrapArrow (arr b c)
instance A.Arrow arr => CartesianCategory (WrappedArrow arr) where
type Product (WrappedArrow arr) = (,)
= WrapArrow (A.arr fst) -- note, here we do
proj1 = WrapArrow (A.arr snd) -- just plumbing
proj2 WrapArrow f &&& WrapArrow g = WrapArrow (f A.&&& g)
```

but cannot do the opposite: there is no way to write `arr`

using `CartesianCategory`

methods.

A simple example of arrow notation in use could be:

```
assoc :: arr ((x,y),z) (x,(y,z))
= proc (xy, z) -> do
assoc <- id -< xy
(x, y) <- id -< (y, z)
yz id -< (x, yz)
```

Note: one doesn't need `returnA = arr id`

, the `id`

is *better*.

How we could desugar the above statements into `CartesianCategory`

combinators? We'll use similar (the same?) approach as Arrow are desugared. Each statement of the form

`<- morphism -< in out `

*takes* `in`

some bindings, and *adds* new `out`

ones. The beginning `proc vars -> ...`

produces initial bindings and the final `combinator -< ...`

assembles final "value".

We can write what variables are in scope after each statement:

```
assoc :: arr ((x,y),z) (x,(y,z))
= proc (xy, z) -> do
assoc -- xy, z
<- id -< xy
(x, y) -- xy, z, x, y
<- id -< (y, z)
yz -- xy, z, x, y, yz
id -< (x, yz)
```

The `Overloaded:Categories`

desugared is very simple, as it essentially maintains a context of `a input variable`

values. To construct tuples it uses `&&&`

to tuple-them up, and when there is tuple-pattern match, `overloaded`

applies `proj1`

and `proj2`

.

For specific example, let us zoom into

```
-- xy, z
<- id -< xy
(x, y) -- xy, z, x, y
```

step. Our goal is to construct

diagram. As we have `xy`

and `z`

variables in scope, we have and arrows. We don't construct tuples in this step, but deconstruct tuple so we will use `proj1`

() and `proj2`

(). To carry the existing bindings over we use `id &&& f`

(`second`

, ) We can draw a diagram of what happens:

The context is transformed to be

```
= xy . proj1
xy = z . proj1
z = proj1 . proj2
x = proj2 . proj2 y
```

using `id &&& id . xy`

.

The next statement tuples up variables:

```
-- xy, z, x, y
<- id -< (y, z)
yz -- xy, z, x, y, yz
```

The context is transformed to be

```
= xy . proj1 . proj1
xy = z . proj1 . proj1
z = proj1 . proj2 . proj1
x = proj2 . proj2 . proj1
y = proj2 yz
```

by `id &&& ((proj2 . proj2) &&& (proj2 . proj1))`

.

And the process continues similarly.

The actual arrow notation desugaring similarly have rules for each statements with input and output contexts.

repetitive fan outs and projections are often redundant,

`overloaded`

applies simplifications like`proj1 . (f &&& g)`

into`f`

, but not all possible to avoid losing possible sharing. The "optimizer" is far from smart.We could be smarter and count which sharing are actually used afterwards, and only carry them over. In the example above

`xy`

is used once, so it doesn't need to be carried over. As far as I understand GHC desugaring does that.Ultimately, we could desugar using

*commutative monoidal category*combinators (In the example above, only`assoc`

is needed).`assoc :: a ((b,c),d) (b,(c,d)) swap :: a (b, c) (c, b)`

But this is not yet supported in

`overloaded`

, as all example categories I wanted to work with were Cartesian.

The go to example for GADTs is well-typed simple typed lambda calculus terms:

```
-- types
data Ty
= TyPair Ty Ty
| TyFun Ty Ty
| TyNat
-- indexing into context
data Elem :: [Ty] -> Ty -> Type where
Here :: Elem (x ': xs) x
There :: Elem xs x -> Elem (y ': xs) x
-- terms
data Term :: [Ty] -> Ty -> Type where
Var :: Elem ctx ty -> Term ctx ty
Lam :: Term (a ': ctx) b -> Term ctx ('TyFun a b)
App :: Term ctx ('TyFun a b) -> Term ctx a -> Term ctx b
Fst :: Term ctx ('TyPair a b) -> Term ctx a
Snd :: Term ctx ('TyPair a b) -> Term ctx b
Pair :: Term ctx a -> Term ctx b -> Term ctx ('TyPair a b)
Nat :: Natural -> Term ctx 'TyNat
```

The `Elem`

value in `Var`

indexes into context. The term values are thus full of `Here`

, `There Here`

etc de Bruijn indices. These are not fun to write.

We can define a helper type:

```
newtype Mapping (ctx :: [Ty]) (a :: Ty) (b :: Ty) =
M (Term ctx ('TyFun a b))
```

which is not only `Category`

, but also `CartesianCategory`

:

```
instance CartesianCategory (Mapping ctx) where
type Product (Mapping ctx) = 'TyPair
= M $ Lam $ Fst var0
proj1 = M $ Lam $ Snd var0
proj2 M f) (M g) = M $ Lam $ Pair
fanout (
(app (weakenTerm f) var0) (app (weakenTerm g) var0)
```

The `assoc`

value we defined above, with the help of `Overloaded:Categories`

, has the type (and can be redefined more concisely):

```
assoc :: CartesianCategory cat
=> cat (Product cat (Product cat a b) c)
Product cat a (Product cat b c))
(= proc ((x, y), z) -> identity -< (x, (y, z)) assoc
```

which when specialized to `Mapping`

produces term (after few reductions):

```
Lam (Pair (Fst (Fst (Var Here)))
Pair (Snd (Fst (Var Here)))
(Snd (Var Here)))) (
```

The arrow-notation is not as concise as Haskell expression `\((x,y),z) -> (x,(y,z))`

, but is nicer than counting de Bruijn indices by hand.

Another example I have worked out is machinery which allows to write automatic diffentiation programs. Like the small xor neural network below:

```
type Input = Leaf2
type NeuronW = 'Plus ('Leaf N.Nat2) Leaf1
type Weights = 'Plus ('Plus NeuronW NeuronW) NeuronW
type WeightsN = Eval Weights
-- single neuron with two inputs
neuron :: AD ('Plus Input NeuronW) Leaf1
= proc (i, (ws, bias)) -> do
neuron <- dot -< (ws, i)
o . plus -< (o, bias)
tanhAD
-- the 2-2-1 network
network :: AD ('Plus Input Weights) Leaf1
= proc (xy, ((w1, w2), w3)) -> do
network <- neuron -< (xy, w1)
u <- neuron -< (xy, w2)
v <- rewrap -< (u, v)
uv -< (uv, w3)
neuron
-- error for xor.
-- This can be more "dynamic", taking values in.
-- We apply gradient descent to minimise this.
networkError :: AD Weights Leaf1
= proc ws -> do
networkError -- xor!
<- ex (1 ::: 1 ::: VNil) 0 -< ws
s1 <- ex (0 ::: 0 ::: VNil) 0 -< ws
s2 <- ex (1 ::: 0 ::: VNil) 1 -< ws
s3 <- ex (0 ::: 1 ::: VNil) 1 -< ws
s4
-< ((s1,s2), (s3, s4))
sumAD where
ex :: V N.Nat2 -> S -> AD Weights Leaf1
= proc ws -> do
ex i e <- konst i -< ()
i1 <- konst (V.singleton e) -< ()
e1 <- network -< (i1, ws)
a1 <- minus -< (e1, a1)
r1 -< (r1, r1) dot
```

Luckily GHC Haskell has (Typed) Template Haskell, so the generated code is quite fast: training this toy-xor-neural network takes a millisecond and evaluation 0.000s.

It would be great if `Arrows`

desugared into `CartesianCategory`

and other (basic) category theory inspired type-classes. However, I haven't told all `arr`

is not used not only to do tuple mangling but also to mangle records into tuples and back and sum-types into `Either`

s (for `ArrowChoice`

combinators). With `Overloaded:Categories`

we are limited to whatever `Product`

or `Coproduct`

types are defined. And what may be confusing, the syntax is always tuples and `Left`

/`Right`

even the product and coproduct are something else. For example Cartesian product i.e. pair is not only product but also a coproduct in - category of vector spaces and linear maps.

The usage of `Overloaded:Categories`

with `proc`

could also be made nicer with heterogeneous lists, so one doesn't need to nest pairs, but use n-tuples. It can be done, but I just had to stop somewhere.

For `Overloaded:Categories`

to cover all of `Arrows`

use cases, we'll need a type-class with `arr`

. In my opinion `arr`

shouldn't be used for the bulk of desugaring, and shouldn't be in the root class of the hierarchy, but rather in a separate branch.

Similar situation is with having `fromInteger`

in `Num`

, the value used for desugaring of integer literals is conflated with kind-of class for ring structures (but with `abs`

and `signum`

), thus if you don't have ring structure you don't use literals. And if you cannot implement `arr`

you don't use arrow-notation. `overloaded`

offers alternative designs.

The `Overloaded:Do`

is one of the new features of recent overloaded 0.2.1 release. `overloaded`

package uses source plugins to reinterpret syntax in different ways.

It solves the same problem as Local Do ghc-proposal, but the details differ.

Before diving into differences between proposal and `overloaded`

approach, we should recall the part of GHC compilation pipeline. We are interested in the frontend steps.

- After parsing the AST with
`RdrNames`

(essentially just strings), is*renamed*to AST with`Name`

s (resolved names, contain package and module names). The resulting AST is made*well-scoped*. - Then that well-scoped surface syntax AST is
*type-checked*and transformed into Core expressions.

The desugaring of built-in constructs (e.g. `do`

notation) happens in type-checking phase. This allows reporting better type-errors (referring to the original source).

On the other hand, `OverloadedStrings`

features are desugared already during *renaming*. The AST string literal node is expanded into `fromString ...`

, where `fromString`

is the `Data.String.fromString`

.

`overloaded`

takes one step forward, and `Overloaded:String`

can be configured to desugar into some other combinator.

Similarly to `OverloadedStrings`

, I'd expect `QualifiedDo`

extension to work in the same phase.

There is also `RebindableSyntax`

extension. It works so, that the AST for `do`

statements is also populated with names it should be desugared to. This is how I should have implemented `Overloaded:Do`

too, but currently I actually desugar statements manually in `OverloadedStrings`

way.

This is short overview of GHC pipeline parts relevant for syntax desugaring. Let's next review the Local Do ghc-proposal.

The idea is that we could write

```
.do
builder<- u
x stmts
```

And it will be desugared into

```
case builder of
K { (>>=) = v } -> v u (\x -> builder.do { stmts })
```

instead of ordinary

`Control.Monad.>>= \x -> do { stmts } u `

This would allow *locally* change how the do-notation is desugared, instead of global `RebindableSyntax`

approach.

Here `builder`

is a value of record data type defined elsewhere as

`data NameIrrelevant = K { (>>=) :: sometype }`

Informally one could think about `QuantifiedDo`

desugaring into:

```
case builder of K {..} -> do
<- u
x stmts
```

with `RebindableSyntax`

semantics only for the outer `do`

block.

I think this desugaring is *not elegant*. If you read the proposal, you will notice that the `builder`

must have *fully settled type T*, which is obscure way to say *we should know the type of builder before type-checking is done*.

Why so you may ask. This is an artifact of Haskell records using in desugaring. In the desugaring, we *have to know* a field `Name`

. Note, the field name is not just a string `">>="`

, but it should be a `Name`

of field of the **right type**.

We can use the same name for fields of different types (e.g. when they are defined in different modules, without any extensions to Haskell98). And these `Name`

s are not the same after the renaming step.

This feels limiting. Vladislav Zavialov (int-index) asked about more "dynamic" approach:

```
data CustomDo m = CustomDo
(>>=) :: forall a b. m a -> (a -> m b) -> m b
{ return :: forall a. a -> m a
,
}
mkCustomDo :: String -> CustomDo IO
= do
main <- getLine
str let customDo = mkCustomDo str
.do
customDoputStrLn "Hello"
putStrLn "World"
```

If I'm reading the proposal right, here the `customDo`

before `do`

is not an expression with fully settled type. You would need to write

```
customDo :: CustomDo IO).do
(putStrLn "Hello"
putStrLn "World"
```

which is just ugly. `Overloaded:Do`

approach doesn't need such extra annotation.

We need to find a way to desugar in a single "global" way. And we have `builder`

expression available.

You can arrive to this approach by thinking about

If field selectors are all different, is there an abstraction making them the same?

To which answer is yes: `GHC.Records`

is one, but not (yet?) powerful enough.

Or you can think through *How I would write this in Agda* (or imaginary Dependent Haskell), which is the way I thought about this originally.

Instead of a record with unique field names, we can have a *dependent function*.

Using pseudo-syntax it would look like:

```
data Method
= Then -- ^ '>>'
| Bind -- ^ '>>='
...
type family BuilderMethodType (m :: Method) :: Type where
BuilderMethodType Then = ...
BuilderMethodType Bind = ...
...
builder :: (m :: Method) -> BuilderMethodType m
Then = ...
builder Bind = ... builder
```

Then our running example

```
.do
builder<- u
x stmts
```

would be desugared into

`GHC.QuantifiedDo.Bind u (\x -> builder.do { stmts } ) builder `

In simple examples this is possible to express in today's GHC Haskell. We need a singleton of `Method`

, and then we can write

```
data SMethod :: Method -> Type where
SBind :: SMethod 'Bind
SThen :: SMethod 'Then
type family BuilderMethodType (method :: Method) :: Type where
BuilderMethodType Then = Int -> Int -> Int
BuilderMethodType Bind = TypeError ('Text "no bind for you")
builder :: SMethod m -> BuilderMethodType m
SThen = (+)
builder SBind = error "error" builder
```

By the way, is there a way to write something else than `error`

for values of impossible types: `TypeError`

or `Int ~ (a, b) => ...`

. Like `EmptyCase`

, but there are nothing to `case`

on.

Then we could use `do`

notation as small addition calculator. The `>>`

will be replaced by `builder SThen`

in:

```
= sugar.do
total 1
2 * 3
4 * 5
```

This approach is currently doomed, we run into problems: If we try to write builder for ordinary `Monad`

s, we'll need `RankNTypes`

as values of a type family:

```
type family MonadMethodType (method :: Method) :: Type where
MonadMethodType Then = forall a b m. Monad m => m a -> m b -> m b
...
```

which will error with

```
Illegal polymorphic type:
• forall a b (m :: * -> *). Monad m => m a -> m b -> m b
In the equations for closed type family ‘MonadMethodType’ •
```

Ok, `TypeFamilies`

don't work (yet?). Luckily we have `FunctionalDependencies`

, which is kind of the same, but sometimes helpfully different. Type class definition is accepted, as there is nothing special. We declare "type-family" and builder-value at the same time. Note the similarity with `GHC.Records.HasField`

.

```
class MonadMethod (m :: Method) (ty :: Type) | m -> ty where
monad :: SMethod m -> ty
```

but when we try to write instance (after enabling scary `ImpredicativeTypes`

):

```
instance
~ (forall a b m. Monad m => m a -> m b -> m b))
(ty => MonadMethod 'Then ty
where
SThen = _ monad
```

GHC-8.8.3 says

```
: panic! (the 'impossible' happened)
ghcGHC version 8.8.3 for x86_64-unknown-linux):
(.injTyVarsOfType unusedInjTvsInRHS
```

Ok. let's try GHC-8.10.1:

```
Found hole:
• _ :: forall a b (m :: * -> *). Monad m => m a -> m b -> m b
```

Nice! exactly what we want. The `>>`

should fit that hole perfectly... except it doesn't...

```
instance
~ (forall a b m. Monad m => m a -> m b -> m b))
(ty => MonadMethod 'Then ty
where
SThen = (>>) monad
```

errors with

```
Couldn't match type ‘m0 a0 -> m0 b0 -> m0 b0’
• m :: * -> *). Monad m => m a -> m b -> m b’
with ‘forall a b (Expected type: ty
Actual type: m0 a0 -> m0 b0 -> m0 b0
```

I run out of ideas how to make GHC-8.10 accept that. I haven't tried whether GHC with Quick Look Impredicativity would accept that. Maybe it would, which will be nice.

The final solution used in `overloaded`

is to not use `FunctionalDependencies`

at all. Then the instances can be written as

```
instance
~ m a -> m b -> m b, Monad m)
(ty => MonadMethod 'Then ty
where
SThen = (>>) monad
```

We can have type-variables in the context which are not used in the instance head (`MonadMethod 'Then ty`

), because they are "defined" by type-equality constraint.

Note: Instances don't need to be written for all methods, or they can be guarded by `TypeError`

. Therefore it's straight-forward to have a desugaring forbidding `fail`

or `>>=`

(if you are using `ApplicativeDo`

). This is a benefit of a "type-approach".

Also the `overloaded`

version doesn't use singletons, but rather `TypeApplications`

and `AllowAmbiguousTypes`

. The `>>`

is desugared into `builder @Then`

. This allows to write builders for ordinary `Monad`

or `IxMonad`

and many others. And in fact, the above is only a sketch how `builder`

could be implemented. Any approach works as far as `builder @method`

type application is legal.

With `overloaded`

we had to diverge from the ideal solution. But as GHC becomes smarter, we could improve.

The Local Do ghc-proposal and Overloaded:Do both solve the same problem of locally altering how `do`

notation is desugared. The machinery is however slightly different.

I consider the proposed variant inelegant, as it introduces (to my understanding) new *fully settled type* concept. The `overloaded`

approach shows it is not necessary. Unfortunately the current GHC functionality is not powerful enough to implement builders elegantly, even the desugaring itself is very simple. Surprisingly even the Local do ghc-proposal have extensive alternatives section, there aren't anything in the Dependent Haskell spirit.

I occasionally write blog posts with some math. So far I have been using `latex-formulae`

family of packages. This week Andres Löh asked whether can be rendered as SVGs.

The answer is **yes**.

The `preview`

CTAN package, and the `dvisvgm`

tool make it very easy. I forked `latex-formulae`

into `latex-svg`

to use above mentioned tools. There are three packages on Hackage now:

- latex-svg-image: render LaTeX formulae to SVG images
- latex-svg-pandoc: render LaTeX formulae in pandoc documents
- latex-svg-hakyll: render LaTeX formulae in hakyll pages

To mention some differences between `latex-formulae`

and `latex-svg`

:

`latex-svg-image`

uses only`latex`

and`dvisvgm`

, ImageMagick*is not required*. You don't need to tweak`policy.xml`

to allow rasterization of PostScript. (See this StackOverflow question).`latex-svg-image`

supports global cache (off by default), which speedups`hakyll`

site builds. My blog builds in 20 seconds instead of three minutes with empty cache. I wouldn't worry about space usage too much, the cache contents take 15M after building my blog. which is way less than the size of`site`

executable.`latex-svg-hakyll`

has`initFormulaCompilerSVGPure`

variant, which doesn't need`IO`

to be created. You don't need to thread`renderFormulae`

function through. Together with global cache, the perfomance penalty is small.One drawback is that result pages become bigger (and slower). For example a formula-heavy https://oleg.fi/gists/posts/2018-12-12-find-correct-laws.html is

`576k`

in size with`latex-formulae`

`2819k`

in size with`latex-svg`

(almost 5 times larger).

Rendering SVG images is also more CPU expensive.

Otherwise the API and module names are the same. If you are already a user of `latex-formulae`

you can easily migrate to `latex-svg`

.

At the end few examples. We can type set quadratic formula

or an exponent tower like

or a charterization of equality of real numbers using "downsets"

from a recent post by Brent Yorgey.

The difference is clearly visible on high-DPI displays, for example mobile devices.

As the font-size can be configured, the inline math like looks nicer. Also note that the baseline is taken into account.

For example you can draw tikz-cd diagrams:

For this to work the `Ext_raw_tex`

pandoc extension should be enabled.

Let's start with a complete example right in the beginning. We could write a Haskell code like:

```
$(generateJS "code" [d|
square :: Int -> Int
square n = n * n
poly :: Int -> Int -> Int
poly x y = square x + 10 * y + 100
res = poly 42 7 |])
```

If we load the module into GHCi, we can try that we have the functions defined:

```
> square 5
λ25
> res
λ1934
```

But additionally there's a `code`

value with JavaScript source code:

```
> :t code
λcode :: [Char] -- i.e. String
> putStr code
λ// square :: Int -> Int
function square (n) {return n * n;
}// poly :: Int -> Int -> Int
function poly (x, y) {return square(x) + 10 * y + 100;
}= poly(42, 7) var res
```

How does this work? Let's walk through in three steps.

The `[d| ... |]`

is a syntax of Template Haskell *declaration quote*. For example, `[d| answer = 42 |]`

would produce a value of type `Q Dec`

, which is an abstract syntax representation of it.

Relatedly, the `$(...)`

is splice syntax. As it appears on the top level, it splices declarations (of the type `Q [Dec]`

, or expressions of the type `Q Exp`

depending on the context) into the module. This functionality is often used to define some boilerplate, e.g. `deriveGeneric`

from `generics-sop`

package to define instances, or `makeLenses`

from `lens`

to define `Lens`

values. (Note that the `$(...)`

wrapper is not strictly required, but being explicit helps understand what happens).

We can write a first version of `generateJS`

, which would pass through the declarations given to it:

```
generateJS1 :: String -> Q [Dec] -> Q [Dec]
= decs generateJS1 _ decs
```

We simply return the declarations given as argument. The result of splicing `$(generateJS1 "somename" [d| some code ... |])`

would be the same as not wrapping that *some codeE* inside splice & quote. Not very interesting yet, but it is a start.

The `Dec`

type is not opaque. We can look into the values, alter them, or do something in addition.

`template-haskell`

library also offers a pretty-printing functionality in `Language.Haskell.TH.Ppr`

module, most importantly `pprint`

function which pretty prints various `template-haskell`

types as Haskell code. Let's play with it:

```
generateJS2a :: String -> Q [Dec] -> Q [Dec]
= do
generateJS2a _ decsQ <- decsQ
decs $ putStr $ unlines $ map pprint decs
liftIO return decs
```

In this snippet we `pprint`

the declarations and `putStr`

them. When we (re)load the module in GHCi, something like

```
square_0 :: GHC.Types.Int -> GHC.Types.Int
= n_1 GHC.Num.* n_1 square_0 n_1
```

will be printed in between other messages. There are few things we want to improve:

- global names are fully qualified (
`GHC.Num.*`

) - local names have
*uniques*(i.e.`_1`

suffix in`n_1`

) - printing to console is not nice for tooling

We can solve two first ones using `syb`

- scrap your boilerplate. All types in `template-haskell`

have instances of `Data`

type class, so using `syb`

is very easy way to do modifications:

```
simplifyNames :: Data a => a -> a
= SYB.everywhere (SYB.mkT simplifyName)
simplifyNames
simplifyName :: Name -> Name
Name occ _) = Name occ NameS simplifyName (
```

We modify *all* `Name`

values inside any `Data`

, using `simplifyName`

. `simplifyName`

then makes all names `NameS`

- *unqualified; dynamically bound*; these names are pretty-printed without prefixes or suffixes. Exactly what we want.

To solve the third issue, let's generate the additional definition containing the literal code. For that we'll need to look into `template-haskell`

library documentation to find the names for combinators to write the code:

```
stringDec :: String -- ^ value name
-> String -- ^ value's value
-> Q Dec
= do
stringDec name' contents <- newName name'
name valD (varP name) (normalB (stringE contents)) []
```

When looking at the `template-haskell`

data structures, one can learn few things about the Haskell surface syntax. One clear thing: it's huge. Also that

```
| bar = 1
foo | otherwise = 2
```

is a valid syntax, though not often used (at least on the top-level). This is we use `normalB`

, and not the expression directly: the body of our value is not guarded, but it could be.

Using `simplifyNmaes`

and `stringDec`

we can define an improved version of of `generateJSa`

:

```
generateJS2b :: String -> Q [Dec] -> Q [Dec]
= do
generateJS2b name decsQ <- decsQ
decs let decs' = map simplifyNames decs
<- stringDec name $ unlines $ map pprint decs'
dec return (dec : decs)
```

Now, when we reload in GHCi, the compiler is silent; yet there's new value defined, `code`

:

```
> putStr code
λsquare :: Int -> Int
= n * n
square n poly :: Int -> Int -> Int
= (square x + (10 * y)) + 100
poly x y = poly 42 7 res
```

Some extra parentheses are fine.

You probably guessed what we will do next. Instead of pretty-printing Haskell as Haskell, we will pretty-print Haskell as JavaScript. The `generateJS3`

is essentially the same as previously:

```
generateJS3 :: String -> Q [Dec] -> Q [Dec]
= do
generateJS3 name decsQ <- decsQ
decs let decs1 = map simplifyNames decs
let decs2 = map generateDec decs1
<- stringDec name $ unlines $ map show decs2
dec return (dec : decs)
```

but instead of `pprint`

we use `generateDec`

. `generateDec`

doesn't handle *all* of Haskell syntax, only the bits we need for our example:

```
generateDec :: Dec -> Doc
@SigD {} = PP.text $ "// " ++ pprint dec
generateDec decFunD name clauses) = generateFun name clauses
generateDec (ValD (VarP name) body []) = generateVal name body
generateDec (=
generateDec dec $ "// unhandled Dec: " ++ show dec PP.text
```

Type signatures (`SigD`

) are put into comments, function definitions (`FunD`

: `fun a b = ...`

) and value definitions (`ValD`

: `val = ...`

) are handled by corresponding `generatefun`

and `generateVal`

functions. Their definitions are in the appendix at the end of the blog post. The last, catch all case, `show`

s the Haskell value, so we can see which cases are unhandled (if any).

As the result, if we once again reload the module in GHCi, the `code`

will have the value as in the introduction:

```
> putStr code
λ// square :: Int -> Int
function square (n) {return n * n;
}// poly :: Int -> Int -> Int
function poly (x, y) {return square(x) + 10 * y + 100;
}= poly(42, 7) var res
```

Is this silly? Well... kind of. Compiling Haskell to JavaScript in this way won't work for all of Haskell, for example type-classes are not resolved, not to mention lazy vs. strict semantics.

Yet this is an example demonstrating actual techniques used in the real world:

For example IOHK Plutus uses the very same approach, see example in their tutorial: https://prod.playground.plutus.iohkdev.io/tutorial/#_writing_basic_plutustx_programs. They use Typed Template Haskell, but I think the idea is similar: Examine

`template-haskell`

values, generate corresponding for "your language". There might be some extra steps, as there often are in the compilers.I use the "capturing the Haskell code" part when working with my template library

`zinza`

.`zinza`

can compile its templates to a Haskell module, which will render the template. Using the`pprint`

trick, I can write the input data definitions once, so they can be inserted into generated module, making it self-contained. (I have yet to write about this workflow in`zinza`

documentation).In a similar spirit, one can capture the

`Q [Dec]`

output of e.g.`makeLenses`

, pretty-print it into a file, and by using a CPP switch rather load a once generated Template Haskell splice from a file. For example on a systems where Template Haskell is rather non-available or just better avoidable in general.Obsidian Systems'

`reflex-platform`

used`-ddump-slices`

and regular expression magic to achieve similar effect. That feels a lot more fragile. AFAIK currently they use a custom GHC which can dump and load Template Haskell splices. That way the loading is cleaner, then using CPP, but at the cost of custom patch. Yet, with a Source Plugin (yet if you don't have Template Haskell, you most likely don't have source plugins either) one could- augment all splices to dump their inputs on the "writer systems"
- load the source of the splices on the "reader systems".

```
generateFun :: Name -> [Clause] -> Doc
Clause pats (NormalB body) decs]
generateFun name [| vars <- mapMaybe isVar pats =
"function"
PP.text <+> ppName name
<+> ppParensCommaSep (map (PP.text . pprint) vars)
<+> PP.char '{'
$$
2 (PP.text "return" <+> generateExp body <> PP.char ';')
PP.nest $$
'}'
PP.char where
VarP var) = Just var
isVar (= Nothing
isVar _ = error $ "difficult function: " ++ pprint name
generateFun name _
generateVal :: Name -> Body -> Doc
NormalB body) =
generateVal name ("var" <+> ppName name <+> PP.char '=' <+> generateExp body
PP.text
ppParensCommaSep :: [Doc] -> Doc
= PP.parens $ PP.hsep $ PP.punctuate PP.comma ds
ppParensCommaSep ds
nameStr :: Name -> String
Name (OccName n) _) = n
nameStr (
ppName :: Name -> Doc
= PP.text . nameStr
ppName
generateExp :: Exp -> Doc
InfixE (Just l) (VarE op) (Just r))
generateExp (| nameStr op `elem` ["*", "+"]
= generateExp l <+> ppName op <+> generateExp r
VarE n) = ppName n
generateExp (AppE f x) =
generateExp (let (g, ys) = extractArguments f [x]
in generateExp g <> ppParensCommaSep (map generateExp ys)
LitE (IntegerL i)) = PP.integer i
generateExp (exp
generateExp = error $ "generateExp: difficult expression -- " ++ show exp
extractArguments :: Exp -> [Exp] -> (Exp, [Exp])
AppE f x) ys = extractArguments f (x : ys)
extractArguments (= (f, ys) extractArguments f ys
```

As you are reading this post, you probably know that there is

- the
`lens`

library by Edward Kmett et al. which is de facto*optics*library for Haskell. It's famous also for its type errors. - the
`optics`

library by Adam Gundry, Andres Löh, Andrzej Rybczak and myself uses different representation for*optics*(note: slanted*optics*is a concept, monospace`optics`

is a library name). I recommend reading through the introduction in the official documentation, especially Comparison with`lens`

section

Some time ago I commented on Reddit, that there are no real experience reports about migrating "real world Haskell codebases" from `lens`

to `optics`

. So I decided to do an experiment. The repository is a public Futurice Haskell code monorepository, which I worked on during my time at the Futurice. The whole codebase is a bit over 70000 lines in 800 files.

One disclaimer is that I do this *for fun* and *out of curiosity*, in other words Futurice didn't ask me to do this (fun is subjective). Another disclaimer is that my experiences shouldn't not be extrapolated into how easy or hard this kind of migration is, only that it's possible. I'm way too familiar with the codebase under "migration", as well as with `lens`

and `optics`

libraries. On the other hand, it turned relatively *easy for me*, and I share my experiences, so *it would be easier for others*.

Before discussing *how*, let me talk a little about *why*.

There may be different reasons why a team would like to migrate from `lens`

(or no `lens`

at all) to `optics`

One **bad reason** is trying to reduce dependency footprint. It won't. Libraries use `lens`

, and that cannot be easily changed. The HMR consists of dozens of small web services, which use

`swagger2`

to get Swagger-UI`amazonka`

to use AWS service`gogol`

to operate with G-Suite`Chart`

to draw pretty graphs

All these libraries depend on `lens`

. But we can use them with `optics`

too, as I'll show later. And even we wouldn't have libraries with lens interface, the `lens`

is there somewhere in codebases of this scale. The HMR build plan consists of *over 500 components*, from which about 400 are dependencies from Hackage. In fact, from this "industrial" point of view, it would be better if `microlens`

didn't exist. It's just more duplicate code somewhere there. In the dependency closure there are e.g.

```
microlens-th-0.4.3.2
microlens-mtl-0.2.0.1
microlens-0.4.11.2
lens-4.17.1
```

There are also multiple implementations of other things, so this problem is not unique to van Laarhoven lens libraries.

My current project has about 450 components in the build plan, so this scale is not unique.

On the other hand, one proper reason to use `optics`

could be better type errors. (I'm too experienced to judge that properly but `optics`

at least tries to produces better errors). Another complelling reason is `OverloadedLabels`

which *just work* with `optics`

. We'll see example of that. Thanks to Andrzej Rybczak PR, `swagger2`

package has `optics`

interface via `OverloadedLabels`

(since version 2.5), and it's neat.

HMR has own prelude. The `futurice-prelude`

package is at the bottom of the package graph, in other words everything else there uses the package and imports `Futurice.Prelude`

module. It's *a very fat* prelude, re-exporting a lot of stuff. It also has a bit of auxiliary modules, which most of the downstream would need.

Having a module imported by everything else is nice, especially as this module currently re-exports the following `lens`

definitions:

```
import Control.Lens
At (..), Getter, Iso, Iso', Ixed (..), Lens, Lens', LensLike,
(LensLike', Prism, Prism', Traversal, Traversal', folded, from, ifoldMap,
ifolded, ifor, ifor_, isn't, iso, itoList, itraverse, itraverse_, lazy,
lens, makeLenses, makePrisms, makeWrapped, over, preview, prism, prism',%=), (%~), (&), (.~), (<&>), (?=), (?~), (^.), (^..),
strict, view, (^?), _1, _2, _3, _Empty, _Just, _Left, _Nothing, _Right) (
```

That's not much, but enough for basic optics usage. We'll change the exports to use `optics`

:

```
import Data.Function ((&))
import Data.Functor ((<&>))
import Optics
AffineTraversal, AffineTraversal', At (..), Getter, Iso, Iso',
(Ixed (..), Lens, Lens', Optic, Optic', Prism, Prism', Traversal,
Traversal', castOptic, coerced, folded, ifoldMap, ifolded, ifor, ifor_,
isn't, iso, itraverse, itraverse_, lens, lensVL, makeLenses, makePrisms,
over, preview, prism, prism', re, simple, traversalVL, traverseOf,%), _1, _2, _3, _Empty, _Just, _Left, _Nothing, _Right)
traversed, (import Optics.Operators ((%~), (.~), (?~), (^.), (^..), (^?))
import Optics.State.Operators ((%=), (?=))
```

and then continue fixing type errors, as usually with refactoring in Haskell.

Careful reader may notice that operators are not exported from the main `Optics`

module. If you don't like them, it's easier to not import them. The `&`

and `<&>`

operators are available directly from modules in `base`

, so we import them from there.

There are few missing or different bits in the `optics`

imports:

The

`from`

is just`re`

.There are no

`LensLike`

; we won't need it. Instead we'll need`Optic`

and`Optic'`

, as well as new kind`AffineTraversal`

and`AffineTraversal'`

(I have written about them).There aren't

`Wrapped`

type-class in`optics`

. We'll replace it with`coerced`

.`coerced`

is a bit too polymorphic, so we'll need to add type-annotations. This is a small drawback. Or we could use named`Iso`

s. It depends.The

`itoList`

and`lazy`

and`strict`

are missing, likely they are easy to implement in the`futurice-prelude`

, so the downstream modules won't even notice.`itoList`

is simple application of`ifoldr`

`itoList :: Optics.FoldableWithIndex i f => f a -> [(i, a)] = Optics.ifoldr (\i x xs -> (i,x) : xs) [] itoList`

The story about

`FunctorWithIndex`

,`FoldableWithIndex`

and`TraversableWithIndex`

is long, but ultimately it would be nice if both`optics`

and`lens`

could use the same type-classes; however it's not that straight forward. So now,`lens`

and`optics`

define their own variants.`strict`

and`lazy`

allow to convert between strict and lazy`Text`

s or`ByteString`

s. We'll do the simple thing, and make isos using`lens`

type-class. This should be good enough for now. Recall,`lens`

is still around.`strict :: L.Strict l s => Iso' l s = iso (L.view L.strict) (L.view L.lazy) strict lazy :: L.Strict l s => Iso' s l = iso (L.view L.lazy) (L.view L.strict) lazy`

Similarly to `lazy`

and `strict`

there is `packed`

and `unpacked`

, but migrating those is *very* trivial:

```
-import Data.Text.Lens (packed, unpacked)
+import Data.Text.Optics (packed, unpacked)
```

**Very important** is to remember to re-export `%`

, the `optics`

composition operator.

In addition we also export

`simple`

and`castOptic`

combinators, we'll need them soon. See optics#286 issue. In`optics`

the identity optic is not`id`

.`lensVL`

and`traversalVL`

which help convert van Laarhoven lenses (from external libraries) to`Optics`

representation.`traverseOf`

: sometimes we use van Laarhoven lenses directly as traversals, that trick doesn't play with`optics`

. For the similar reason we export`traversed`

:`traverse`

is not an`Optic`

.

One thing, which I would liked to be able to do is to re-export `lens`

module qualified, something like:

```
module Futurice.Prelude (
...
module qualified L
where )
```

It would helped with this migration, but also help to re-export `Data.Map`

and `Data.ByteString`

etc. that would be bery nice for fat preludes.

This is it, about the prelude. Next I'll list various issues I run into when trying to make a single service in HMR to compile. I picked a particular one, which I remember uses `lens`

a lot for business domain stuff.

To conduct this experiment I:

- Added
`optimization: False`

to`cabal.project.local`

to make compilation faster `cabal build checklist-app:libs`

- On error
`ghcid -c 'cabal repl failing-lib'`

, fix errors in that package - go to step 2.

This is by far the most common type of errors:

```
Couldn't match type
• -core-0.2:Optics.Internal.Optic.Optic
‘optics-core-0.2:Optics.Internal.Optic.Types.A_Lens
optics-core-0.2:Optics.Internal.Optic.TypeLevel.NoIx
optics
s0
t0
a1
b1’-> b0’
with ‘a0 Expected type: a0 -> b0
Actual type: Lens s0 t0 a1 b1
```

The important bit is

```
Expected type: a0 -> b0
Actual type: Lens s0 t0 a1 b1
```

That means that we need to replace dot operator `.`

with the optics composition combinator `%`

. Another variation on the same is

```
Precedence parsing error
.’ [infixr 9] and ‘%’ [infixl 9] in the same
cannot mix ‘ infix expression
```

which happens when you forgot to change few dots.

As already mentioned, `swagger2`

has `optics`

interface; the needed instances are defined in `Data.Swagger.Optics`

module. I imported it into `Orphans`

module of `futurice-prelude`

, to make the instances available everywhere.

The most changes are then of following flavor:

```
- & Swagger.type_ ?~ Swagger.SwaggerObject
- & Swagger.properties .~ InsOrdHashMap.fromList ...
+ & #type ?~ Swagger.SwaggerObject
+ & #properties .~ InsOrdHashMap.fromList ...
```

I honestly just used regexps: `s/& Swagger./\& #/`

, and `s/type_/type/`

.

In one place I had to add a type annotation, as the type become ambiguous. This is not necessarily a bad thing.

```
+ schema :: Swagger.Referenced Swagger.Schema -> Swagger.Schema
schema s = mempty
```

That was very straight-forward, as there **is** `optics`

support in the `swagger2`

library now. Thanks Andrzej!

Unfortunately `gogol`

and `amazonka`

don't have `optics`

support, as far as I know. Both libraries use `lens`

to provide getters and setters to Google Cloud and AWS domain types.

For the code which operates with the libraries directly (which is relatively few modules, API is encapsulated), I `import qualified Control.Lens as L`

and prefix operators with `L.`

.

The resulting code is a slight mess, as you could have both `^.`

from `optics`

, and `L.^.`

from `lens`

. That's not nice even it works.

A solution would be to invest a day and define a bunch of `LabelOptic`

instances for `gogol`

, `amazonka`

and `Chart`

types. One could drop prefixes at the same time. I'd probably write some Template Haskell to automate that task (TH would be more fun than typing all the definitions by hand). Something like:

```
$(convertToLabelOptics (drop 3)
[ ''cleSummary
, ''cleConferenceProperties...
, ]
```

or maybe even reify module contents, look for lenses and do even more magical thing. It would be more uniform, than doing it by hand. AWS and GoogleCloud APIs are huge, and it's hard to know what part you will need next.

`amazonka`

and `gogol`

libraries are code generated, so one other option is to hack the generator to produce an `optics`

packages too.

`Chart`

is not much different API lens-wise, though smaller. There the manual creation of `Chart-optics`

might be viable.

In one place the HMR actually used `Rational`

, and the `Rational`

smart constructor `%`

. In that module the optics weren't used, so I went with `hiding ((%))`

. Maybe I'd defined `rational`

named constructor if I needed it more.

In one library integrating with peculiar JSON API, Futurice uses `lens-aeson`

, luckily there's also `aeson-optics`

so the that issue is fixed by changing the import.

In that same spot we run into other difference between `optics`

and `lens`

: `^.`

in optics really wants a getter. You cannot give it a `Prism`

like `_String`

. `lens`

behavior was (ab)used to return `mempty`

i.e. empty `Text`

on non-match. I think using `foldOf`

is better, though a combinator requiring `AffineFold`

would been even better (i.e. fold resulting at most one value, the non-match could be still `mempty`

, or `def`

from `Default`

).

Similarly in some places `^?`

were used with folds to get the first value. There `headOf`

is semantically more correct.

By the way, we debated whether we should renamed more stuff for `optics`

, but settled to keep the names mostly the same. It really shows in the migration overall. Many things just work out of the box, after changing the imports.

`futurice-prelude`

defines a following type-class:

```
class Ixed m => Pick m where
-- :: Index m -> Lens' m (IxValue m)
pick :: Functor f => Index m -> LensLike' f m (IxValue m)
instance Eq e => Pick (e -> a) where
= p (f e) <&> \a e' -> if e == e' then a else f e'
pick e p f {-# INLINE pick #-}
```

It's useful when working with `Representable`

containers, where `Rep f`

, i.e. index is some enumerable type. For example:

`data PerDayOfWeek a = PWD a a a a a a a`

which can be indexable (representble?) by `DayOfWeek`

. One can use `PerDayOfWeek`

to aggregate data per day of the week. I find that quite common need.

One could directly convert that class to use `optics`

, but that is unnecessary. `optics`

' `ix`

combinator could be stronger than default `AffineTraversal`

, for example a `Lens`

for `Representable`

containers. In my opinion this simplifies code, as one uses the same combinator -- `ix`

-- to index `Map`

s and the types like `PerDayOfWeek`

.

```
instance Ixed (PerDayOfWeek a) where
type IxKind (PerDayOfWeek a) = A_Lens
= lensVL gix ix
```

where `gix`

derives the Lens generically.

HMR has also plenty classy lens type-classes, defined manually. There the identity instance needs to be implemnted as `castOptic`

`simple`

:

```
class HasUUID a where
uuid :: Lens' a UUID
instance HasUUID UUID where- uuid = id
+ uuid = castOptic simple
```

Another alternative would be to the scratch whole class, and rather define

`type HasUuid a = LabelOptic "uuid" A_Lens a a UUID UUID`

and use `OverloadedLabels`

.

In few places HMR uses `lens`

interface to libraries, which don't have an `optics`

counterpart yet. That's where one could selectively sprinkle `lensVL`

:

```
-name = datatypeInfo (Proxy :: Proxy a) ^. datatypeName . packed
+name = datatypeInfo (Proxy :: Proxy a) ^. lensVL datatypeName % packed
```

(The library in question is `generics-sop-lens`

, and in fact there is an unreleased `optics`

variant: `optics-sop`

)

Another use-case for `lensVL`

is when some lenses are defined manually, directly using their van Laarhoven encoding:

```
-worldTasks f (World es ts ls is arc _ _) = f ts <&> ...
+worldTasks = lensVL $ \f (World es ts ls is arc _ _) -> f ts <&> ...
```

Here we move things a bit and insert `lensVL`

in one place, thus avoiding rewriting the actual code of the lens.

One may notice that `optics`

doesn't have types like `Getting`

, `ALens`

or `ATraversal`

. That is because `optics`

types aren't `RankNTypes`

, so `Lens`

works as well as `ALens`

. Almost.

You may need to do rewrites similar to the following one:

```
-toIdMapOf :: HasKey a => Getting (Endo [a]) s a -> s -> IdMap a
+toIdMapOf :: (HasKey a, Optics.Is k A_Getter)
+ => Optic' k is s a -> s -> IdMap a
```

This is not nice, but that's what we have in `optics`

. (Not that `Endo [a]`

is nice either).

One could write also

`toIdMapOf :: HasKey a => Getter s a -> s -> IdMap a`

but that would accept **only** a `Getter`

(same for `lens`

IIRC), thus we need to jump through a hoop to make more usable definitions.

This a thing which **is renamed** in `optics`

, indexed variants are named more shortly, in this case you are looking for `IxFold`

. The indexed optics are well supported in `optics`

, and though they are slightly different in their interface, I didn't run into show stopper problems.

There are no `withIndex`

in `optics`

. In HMR it was used in a following snippet:

`% withIndex % alongside (to EnumValue) id % ifolded) im toMapOf (ifolded `

Let's try to understand what happens there. We fold with index, drop down the index into value, map over the index, and as we have `(newIndex, value)`

we make an indexed fold with the new index.

Why not just remap index directly using `reindexed`

:

`%& reindexed EnumValue) im toMapOf (ifolded `

Turns out we don't need `withIndex`

here. One could use migration to `optics`

as an opportunity to make a code review scan of their codebase.

Note the composition-like combinator, `%&`

, it allows to post-process optics with "optics transformers", which aren't optics themselves, like `reindexed`

. `%`

and `%&`

are left associative (`.`

is right associative), so the above `ifolded &% reindexed EnumValue`

would work as a part of a bigger optic too.

In one module the `ALens`

type was used, with its special operators `#~`

, `^#`

etc. You sometimes need to take a whole `ALens`

in, if you both `view`

and `set`

. With `optics`

one can use `Lens`

with `.~`

and `^.`

.

And that's the last noteworthy issue. After a while, everything compiles and even tests pass on the first run.

I hope that this (almost) "real case study" illustrates some issues which one could run into when moving to use `optics`

, in old or new codebase.

It's worth mentioning that the most tricky issues were inside the auxiliary libraries. The core domain logic, with types which had optics build with `makeLenses`

require mostly only changing `.`

to `%`

.

The biggest obstacle are libraries which have `lens`

i.e. van Laarhoven encoding interfaces. Yet, creating `optics`

interface for them in advance is not insurmountable task.

Whether `optics`

is better for your team is to your team to decide, `optics`

are suitable for "real world haskell".

Semigroups, semigroupoids... are there more semithings?

Let’s start "from the beginning". Groups is 19th century thing. A *group* is a set with a binary operation , identity element and inverse element for each . With an obvious laws you can imagine relating these.

If we remove *identity* element from a group, "obviously" we get a *semigroup*. Because if there’s *any* element , we can recover the identity element by .

So what’s a semigroup with identity element? For sometimes it were just that, until we started call it *monoid*. Go figure, naming is hard, not only in programming, but also in mathematics.

You are hopefully familiar with a concept of a category. I repeat a definition here:

*Error:*LaTeX failed:

```
This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) (preloaded format=latex)
restricted \write18 enabled.
entering extended mode
(./working.tex
LaTeX2e <2017-04-15>
Babel <3.18> and hyphenation patterns for 7 language(s) loaded.
(/usr/share/texlive/texmf-dist/tex/latex/extsizes/extarticle.cls
Document Class: extarticle 1996/10/08 v1.0 Non Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/extsizes/size14.clo)
(/usr/share/texlive/texmf-dist/tex/latex/base/exscale.sty))
(/usr/share/texmf/tex/latex/preview/preview.sty
(/usr/share/texmf/tex/latex/preview/prtightpage.def))
(/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty
(/usr/share/texlive/texmf-dist/tex/latex/base/t1enc.def))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty)
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty)
(/usr/share/texlive/texmf-dist/tex/latex/stmaryrd/stmaryrd.sty)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/palatino.sty)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/mathpazo.sty)
(/usr/share/texlive/texmf-dist/tex/latex/mathtools/mathtools.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty)
(/usr/share/texlive/texmf-dist/tex/latex/tools/calc.sty)
(/usr/share/texlive/texmf-dist/tex/latex/mathtools/mhsetup.sty))
(/usr/share/texlive/texmf-dist/tex/latex/prftree/prftree.sty)
(/usr/share/texlive/texmf-dist/tex/latex/tikz-cd/tikz-cd.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.t
ex)) (/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def
(/usr/share/texlive/texmf-dist/tex/latex/ms/everyshi.sty))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty)
(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/graphics.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/graphics-def/dvips.def)))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.t
ex)) (/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvips.def
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-postsc
ript.def)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.
tex)) (/usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonomet
ric.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.cod
e.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerari
thmetics.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.
code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.c
ode.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformation
s.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.t
ex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.
tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.c
ode.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.
tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex
) (/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex
)
(/usr/share/texlive/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65
.sty)
(/usr/share/texlive/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18
.sty)) (/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgffor.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/math/pgfmath.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibrarytopaths.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/tikz-cd/tikzlibrarycd.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibrarymatrix.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibraryquotes.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/libraries/pgflibraryarrows.meta.
code.tex)))
No file working.aux.
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/t1ppl.fd)
Preview: Fontsize 14.4pt
ABD: EveryShipout initializing macros
! LaTeX Error: Environment definition undefined.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.22 \begin{definition}
[Awodey 1.1]\textbf{Definition} (Awodey 1.1)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omsppl.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/ot1ppl.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omlzplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omszplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omxzplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/stmaryrd/Ustmry.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/ot1zplm.fd)
! LaTeX Error: \begin{preview} on input line 21 ended by \end{definition}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.61 \end{definition}
Preview: Tightpage -32891 -32891 32891 32891
[1] (./working.aux) )
(see the transcript file for additional information)
Output written on working.dvi (1 page, 6704 bytes).
Transcript written on working.log.
```

If you think hard (or read a book), you’ll learn that a single object category is a monoid: category arrows are monoid elements, and the laws work out.

The group analogue is called *groupoid*. In addition to category data, we require that for each arrow there is an inverse arrow , such that and . Or more succinctly: that each arrow is an isomorphism.

But we can also remove stuff: if we remove identity arrows, and unit law we get *semigroupoid*.

*Error:*LaTeX failed:

```
This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) (preloaded format=latex)
restricted \write18 enabled.
entering extended mode
(./working.tex
LaTeX2e <2017-04-15>
Babel <3.18> and hyphenation patterns for 7 language(s) loaded.
(/usr/share/texlive/texmf-dist/tex/latex/extsizes/extarticle.cls
Document Class: extarticle 1996/10/08 v1.0 Non Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/extsizes/size14.clo)
(/usr/share/texlive/texmf-dist/tex/latex/base/exscale.sty))
(/usr/share/texmf/tex/latex/preview/preview.sty
(/usr/share/texmf/tex/latex/preview/prtightpage.def))
(/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty
(/usr/share/texlive/texmf-dist/tex/latex/base/t1enc.def))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty)
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty)
(/usr/share/texlive/texmf-dist/tex/latex/stmaryrd/stmaryrd.sty)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/palatino.sty)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/mathpazo.sty)
(/usr/share/texlive/texmf-dist/tex/latex/mathtools/mathtools.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty)
(/usr/share/texlive/texmf-dist/tex/latex/tools/calc.sty)
(/usr/share/texlive/texmf-dist/tex/latex/mathtools/mhsetup.sty))
(/usr/share/texlive/texmf-dist/tex/latex/prftree/prftree.sty)
(/usr/share/texlive/texmf-dist/tex/latex/tikz-cd/tikz-cd.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.t
ex)) (/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def
(/usr/share/texlive/texmf-dist/tex/latex/ms/everyshi.sty))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty)
(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/graphics.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/graphics-def/dvips.def)))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.t
ex)) (/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvips.def
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-postsc
ript.def)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.
tex)) (/usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonomet
ric.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.cod
e.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerari
thmetics.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.
code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.c
ode.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformation
s.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.t
ex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.
tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.c
ode.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.
tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex
) (/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex
)
(/usr/share/texlive/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65
.sty)
(/usr/share/texlive/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18
.sty)) (/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgffor.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/math/pgfmath.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibrarytopaths.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/tikz-cd/tikzlibrarycd.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibrarymatrix.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibraryquotes.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/libraries/pgflibraryarrows.meta.
code.tex)))
No file working.aux.
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/t1ppl.fd)
Preview: Fontsize 14.4pt
ABD: EveryShipout initializing macros
! LaTeX Error: Environment definition undefined.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.22 \begin{definition}
\textbf{Definition}
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omsppl.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/ot1ppl.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omlzplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omszplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omxzplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/stmaryrd/Ustmry.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/ot1zplm.fd)
! LaTeX Error: \begin{preview} on input line 21 ended by \end{definition}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.51 \end{definition}
Preview: Tightpage -32891 -32891 32891 32891
[1] (./working.aux) )
(see the transcript file for additional information)
Output written on working.dvi (1 page, 6252 bytes).
Transcript written on working.log.
```

A reader probably ask themselves: are there interesting, not-contrived examples of semigroupoids, which aren’t also categories? There are. If poset (set with partial order) is an example of category, then a set with strict order^{1}, is an example of semigroupoid.

As a concrete example, natural numbers with an unique arrow between and when is a semigroupoid.

There are no identity arrow, as , but associativity works out: if and then . Let’s call this semigroupoid .

Finally, a plot twist. nLab calls semigroupoids semicategories, and don’t even mention a semigroupoid as an alternative name!

Recall a definition of functor.

*Error:*LaTeX failed:

```
This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) (preloaded format=latex)
restricted \write18 enabled.
entering extended mode
(./working.tex
LaTeX2e <2017-04-15>
Babel <3.18> and hyphenation patterns for 7 language(s) loaded.
(/usr/share/texlive/texmf-dist/tex/latex/extsizes/extarticle.cls
Document Class: extarticle 1996/10/08 v1.0 Non Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/extsizes/size14.clo)
(/usr/share/texlive/texmf-dist/tex/latex/base/exscale.sty))
(/usr/share/texmf/tex/latex/preview/preview.sty
(/usr/share/texmf/tex/latex/preview/prtightpage.def))
(/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty
(/usr/share/texlive/texmf-dist/tex/latex/base/t1enc.def))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty)
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty)
(/usr/share/texlive/texmf-dist/tex/latex/stmaryrd/stmaryrd.sty)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/palatino.sty)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/mathpazo.sty)
(/usr/share/texlive/texmf-dist/tex/latex/mathtools/mathtools.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty)
(/usr/share/texlive/texmf-dist/tex/latex/tools/calc.sty)
(/usr/share/texlive/texmf-dist/tex/latex/mathtools/mhsetup.sty))
(/usr/share/texlive/texmf-dist/tex/latex/prftree/prftree.sty)
(/usr/share/texlive/texmf-dist/tex/latex/tikz-cd/tikz-cd.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.t
ex)) (/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def
(/usr/share/texlive/texmf-dist/tex/latex/ms/everyshi.sty))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty)
(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/graphics.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/graphics-def/dvips.def)))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.t
ex)) (/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvips.def
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-postsc
ript.def)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.
tex)) (/usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonomet
ric.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.cod
e.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerari
thmetics.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.
code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.c
ode.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformation
s.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.t
ex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.
tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.c
ode.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.
tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex
) (/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex
)
(/usr/share/texlive/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65
.sty)
(/usr/share/texlive/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18
.sty)) (/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgffor.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/math/pgfmath.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibrarytopaths.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/tikz-cd/tikzlibrarycd.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibrarymatrix.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibraryquotes.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/libraries/pgflibraryarrows.meta.
code.tex)))
No file working.aux.
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/t1ppl.fd)
Preview: Fontsize 14.4pt
ABD: EveryShipout initializing macros
! LaTeX Error: Environment definition undefined.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.22 \begin{definition}
[Awodey 1.2]\textbf{Definition} (Awodey 1.2)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/ot1ppl.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omlzplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omszplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omxzplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/stmaryrd/Ustmry.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/ot1zplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omsppl.fd)
! LaTeX Error: \begin{preview} on input line 21 ended by \end{definition}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.37 \end{definition}
Preview: Tightpage -32891 -32891 32891 32891
[1] (./working.aux) )
(see the transcript file for additional information)
Output written on working.dvi (1 page, 5988 bytes).
Transcript written on working.log.
```

Functors preserve identities, but semigroupoids don’t have identities to be preserved. We need a weaker concept:

*Error:*LaTeX failed:

```
This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) (preloaded format=latex)
restricted \write18 enabled.
entering extended mode
(./working.tex
LaTeX2e <2017-04-15>
Babel <3.18> and hyphenation patterns for 7 language(s) loaded.
(/usr/share/texlive/texmf-dist/tex/latex/extsizes/extarticle.cls
Document Class: extarticle 1996/10/08 v1.0 Non Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/extsizes/size14.clo)
(/usr/share/texlive/texmf-dist/tex/latex/base/exscale.sty))
(/usr/share/texmf/tex/latex/preview/preview.sty
(/usr/share/texmf/tex/latex/preview/prtightpage.def))
(/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty
(/usr/share/texlive/texmf-dist/tex/latex/base/t1enc.def))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty)
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty)
(/usr/share/texlive/texmf-dist/tex/latex/stmaryrd/stmaryrd.sty)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/palatino.sty)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/mathpazo.sty)
(/usr/share/texlive/texmf-dist/tex/latex/mathtools/mathtools.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty)
(/usr/share/texlive/texmf-dist/tex/latex/tools/calc.sty)
(/usr/share/texlive/texmf-dist/tex/latex/mathtools/mhsetup.sty))
(/usr/share/texlive/texmf-dist/tex/latex/prftree/prftree.sty)
(/usr/share/texlive/texmf-dist/tex/latex/tikz-cd/tikz-cd.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.t
ex)) (/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def
(/usr/share/texlive/texmf-dist/tex/latex/ms/everyshi.sty))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty)
(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/graphics.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/graphics-def/dvips.def)))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.t
ex)) (/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvips.def
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-postsc
ript.def)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.
tex)) (/usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonomet
ric.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.cod
e.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerari
thmetics.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.
code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.c
ode.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformation
s.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.t
ex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.
tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.c
ode.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.
tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex
) (/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex
)
(/usr/share/texlive/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65
.sty)
(/usr/share/texlive/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18
.sty)) (/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgffor.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/math/pgfmath.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibrarytopaths.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/tikz-cd/tikzlibrarycd.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibrarymatrix.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibraryquotes.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/libraries/pgflibraryarrows.meta.
code.tex)))
No file working.aux.
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/t1ppl.fd)
Preview: Fontsize 14.4pt
ABD: EveryShipout initializing macros
! LaTeX Error: Environment definition undefined.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.22 \begin{definition}
\textbf{Definition}
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/ot1ppl.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omlzplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omszplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omxzplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/stmaryrd/Ustmry.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/ot1zplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omsppl.fd)
! LaTeX Error: \begin{preview} on input line 21 ended by \end{definition}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.36 \end{definition}
Preview: Tightpage -32891 -32891 32891 32891
[1] (./working.aux) )
(see the transcript file for additional information)
Output written on working.dvi (1 page, 5700 bytes).
Transcript written on working.log.
```

An identity functor is obviously a semifunctor, also a successor functor is a semifunctor .

In Haskell, that would be silly to define a class for (endo)semifunctors:

```
-- semimap f . semimap g = semimap (f . g)
class Semifunctor f where
semimap :: (a -> b) -> f a -> f b
```

It’s the `Functor`

type-class without an identity law. On the other hand, something like

```
data Mag a b t where
Map :: (x -> t) -> Mag a b x -> Mag a b t
One :: a -> Mag a b b
instance Semifunctor (Mag a b) where
fmap f (Map g x) = Map (f . g) x
fmap f x = Map f x
```

would be valid.

Now as we have semifunctors, would it make sense to ask whether endosemifunctors can form a monad

*Error:*LaTeX failed:

```
This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) (preloaded format=latex)
restricted \write18 enabled.
entering extended mode
(./working.tex
LaTeX2e <2017-04-15>
Babel <3.18> and hyphenation patterns for 7 language(s) loaded.
(/usr/share/texlive/texmf-dist/tex/latex/extsizes/extarticle.cls
Document Class: extarticle 1996/10/08 v1.0 Non Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/extsizes/size14.clo)
(/usr/share/texlive/texmf-dist/tex/latex/base/exscale.sty))
(/usr/share/texmf/tex/latex/preview/preview.sty
(/usr/share/texmf/tex/latex/preview/prtightpage.def))
(/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty
(/usr/share/texlive/texmf-dist/tex/latex/base/t1enc.def))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty)
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty)
(/usr/share/texlive/texmf-dist/tex/latex/stmaryrd/stmaryrd.sty)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/palatino.sty)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/mathpazo.sty)
(/usr/share/texlive/texmf-dist/tex/latex/mathtools/mathtools.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty)
(/usr/share/texlive/texmf-dist/tex/latex/tools/calc.sty)
(/usr/share/texlive/texmf-dist/tex/latex/mathtools/mhsetup.sty))
(/usr/share/texlive/texmf-dist/tex/latex/prftree/prftree.sty)
(/usr/share/texlive/texmf-dist/tex/latex/tikz-cd/tikz-cd.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.t
ex)) (/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def
(/usr/share/texlive/texmf-dist/tex/latex/ms/everyshi.sty))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty)
(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/graphics.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/graphics-def/dvips.def)))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.t
ex)) (/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvips.def
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-postsc
ript.def)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.
tex)) (/usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonomet
ric.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.cod
e.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerari
thmetics.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.
code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.c
ode.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformation
s.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.t
ex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.
tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.c
ode.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.
tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex
) (/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex
)
(/usr/share/texlive/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65
.sty)
(/usr/share/texlive/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18
.sty)) (/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgffor.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/math/pgfmath.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibrarytopaths.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/tikz-cd/tikzlibrarycd.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibrarymatrix.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tik
zlibraryquotes.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/libraries/pgflibraryarrows.meta.
code.tex)))
No file working.aux.
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/t1ppl.fd)
Preview: Fontsize 14.4pt
ABD: EveryShipout initializing macros
! LaTeX Error: Environment definition undefined.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.22 \begin{definition}
\textbf{Semimonad}
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/ot1ppl.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omlzplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omszplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omxzplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/stmaryrd/Ustmry.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/ot1zplm.fd)
(/usr/share/texlive/texmf-dist/tex/latex/psnfss/omsppl.fd)
! LaTeX Error: \begin{preview} on input line 21 ended by \end{definition}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.37 \end{definition}
Preview: Tightpage -32891 -32891 32891 32891
[1] (./working.aux) )
(see the transcript file for additional information)
Output written on working.dvi (1 page, 5968 bytes).
Transcript written on working.log.
```

Looks a lot like monad, but for semifunctors. I have an example: the semifunctor is a semimonad. Feels like (I didn’t check) that all strictly monotonic functions would fit. We need to find some more structured semigroupoid than to find more interesting semimonads, but I haven’t yet.

I end with a catchy phrase:

*A semimonad is a monoid (!) in the category of endosemifunctors.*

What would be a semigroup in the category of endofunctors^{2}, or a semigroup in the category of endosemifunctors?

Naming is hard.

There’s a paper *The theory of semi-functors* by Raymond Hoofman https://doi.org/10.1017/S096012950000013X.

http://mathworld.wolfram.com/StrictOrder.html, I not dare to call the set with strict order a soset↩︎

in Haskell we call it

`Bind`

, at least now (or`Apply`

for different semigroup)↩︎

Not so long ago, an older post of mine about LLC in Agda circulated on Twitter. One comment was: *it’s typing with leftovers!*. What does that mean? you may ask; let me show.

This is the post with fancy LaTeX formulas :)

In Church encoding of linear types post, we wrote a right rule for times as (slightly adjusted)

```
==> x : X Γ ==> y : Y
Γ ---------------------------- ⊗R
==> pair x y : X ⊗ Y Γ₁,Γ₂
```

And the fancy LaTeX version of it looks like:

In this version, we somehow know how to split the context into two parts, to construct halves of times-pair.

Another way to formulate rules, is using leftover contexts:

We start with context, try to construct . Its construction uses as much stuff from context as it needs, leaving over some context . Then we continue with context trying to construct , and get another residual context . So starting with context, we can construct a pair , with a leftover .

We’ll need few more rules to make large enough fragment of logic to show meaningful example: Identity rule, left rule for times an right and left rules for linear implication and one. This fragment is called *Multiplicative Intuitionistic Linear Logic*, or MILL for short.

Let us see how this work in practice. Let’s write