Войти в систему

Home
    - Создать дневник
    - Написать в дневник
       - Подробный режим

LJ.Rossia.org
    - Новости сайта
    - Общие настройки
    - Sitemap
    - Оплата
    - ljr-fif

Редактировать...
    - Настройки
    - Список друзей
    - Дневник
    - Картинки
    - Пароль
    - Вид дневника

Сообщества

Настроить S2

Помощь
    - Забыли пароль?
    - FAQ
    - Тех. поддержка



Пишет Journal de Chaource ([info]lj_chaource)
@ 2018-03-04 22:25:00


Previous Entry  Add to memories!  Tell a Friend!  Next Entry
Monoids and co-monoids
The writer monad, `W a = (a, w)` usually assumes a monoid as its fixed type `w`. The reader monad, `R a = r -> a`, does not assume any properties for its fixed type `r`. I realized that this asymmetry is an illusion. In fact, the reader monad assumes a co-monoid for `r`.

A type `w` is a monoid if there exist two methods, `unit: 1 -> w` and `combine: (w, w) -> w`. The `combine` operation must be associative. The unit must be the identity element for the `combine` operation.

Inverting the arrow directions, we obtain the definition of co-monoid:

A type `r` is a co-monoid if there exist two methods, `counit: r -> 1` and `expand: r -> (r, r)`. The `expand` operation must be co-associative.

The co-associativity means that fst (expand (snd (expand r))) = snd( expand (fst (expand r))).

In other words, `expand` is a function product made of two functions, `expand1 : r -> r` and `expand2 : r -> r`. Co-associativity means that these two functions must commute.

Note that the `counit` always exists and even is unique because `1` is the terminal object in the category, which always exists as far as functional programming is concerned. So we can just omit `counit` from the definition of the co-monoid. The result is the definition of co-semigroup. So, co-semigroups and co-monoids are the same thing for the purposes of functional programming.

The reader monad is defined via the `join` method:

`join: (r -> (r -> a)) -> r -> a`
`join rra = r -> rra r r`

To implement `join`, we need two copies of `r`. Clearly, we are tacitly using the `expand` operation here. The trivial definition `expand r = (r, r)` is a co-monoid for any type r. For this reason, we did not notice that a co-monoid is actually being used. Making this explicit, we find the definition of `join` like this:

`join rra = r -> (uncurry rra) (expand r)`

Now, the writer monad can be weakened to the writer pre-monad, by omitting the `unit` operation and reducing the monoid W to a semigroup. No such weakening is necessary for the reader monad, because co-monoids and co-semigroups are the same.

We have seen that any type `r` is trivially a co-monoid. What are nontrivial examples of generic co-monoid types?

I found two examples so far.

1. Consider the triple `(t, t, t)` of the same type `t`. The `expand` operation will copy the middle value towards the middle:

expand (x, y, z) = ((x, y, y), (y, y, z))

Co-associativity is achieved because any composition of `expand` will always yield a structure of the form (x, y, y), (y, y, y), ..., (y, y, y), (y, y, z).

The two functions are `expand1 (x,y,z) = (x, y, y)` and `expand2 (x,y,z) = (y, y, z)`.
The composition of `expand1` and `expand2` in any order gives `(y, y, y)`, which shows co-associativity of `expand`.

2. Consider a list type `List t` and define `expand` as follows:

expand [] = ([], [])
expand [x] = ([], [])
expand [x, ..., y] = ([x, ...], [..., y])

The composition of `expand1` and `expand2` gives the middle piece `...` from the initial list, or the empty list if it's too short.

These examples are similar because they operate on the "accordion" principle: the data type has a "middle piece" that is being expanded by copying. Are there other examples of nontrivial co-monoids that operate in a different way?


(Читать комментарии) (Добавить комментарий)