Класс типов для (что кажется) контравариантного функтора, реализующего инверсию функции

Допустим, у меня есть следующее

import Control.Category (Category, (.), id)

data Invertible a b = Invertible (a -> b) (b -> a)

instance Category Invertible where
  id = Invertible Prelude.id Prelude.id
  (Invertible f f') . (Invertible g g') = 
    Invertible (f Prelude.. g) (g' Prelude.. f')

invert (Invertible x y) = Invertible y x

Обратите внимание, что верно следующее:

invert (g . f) == invert f . invert g

Эта структура кажется очень похожей на контравариантный функтор (википедия), поскольку следует той же самой аксиоме:

 F(g . f) = F(f) . F(g) 

В моем случае, F это просто invert,

Я посмотрел на Data.Functor.Contravariant.contramap, который имеет функцию типа:

(a -> b) -> f b -> f a

Но я не знал, как бы я реализовал это в моей ситуации. Например, я не могу выработать разумный выбор для fи в моей ситуации нет функции a -> b, просто invert,

Тем не мение, invert тем не менее, соответствует математической аксиоме контравариантного функтора, поэтому я думаю, что могу вписать это в какой-то существующий класс, но я просто не могу найти, какой и как это сделать. Любая помощь или указатели будут оценены.

1 ответ

Категория имеет две коллекции: объекты и морфизмы.

Обычная прелюдия Хаскелла, и кажется, что классы в Data.Functor.Contravariant, работают только с очень узкой категорией, то есть категорией, в которой типы являются объектами, а функции - морфизмами, обычно обозначаемыми как Hask. Стандарт Functor класс также очень узок: они представляют только эндофункторы в Hask: они должны относить типы к типам и функции к функциям.

Взять к примеру функтор Maybe, Путь Maybe действует на типы только то, что он принимает типы a в Maybe a, Maybe карты Int в Maybe Int и так далее (я знаю, это звучит немного тривиально). Что это делает с морфизмами, закодировано fmap: fmap принимает f :: (a -> b), морфизм между двумя объектами в Hask, и отображает его в fmap f :: (Maybe a -> Maybe b)еще один морфизм в Hask между объектами, на которые отображается функтор. В Хаскеле мы не могли определить Functor например, Int в Char - все на Хаскеле Functors должны быть конструкторами типов - но в общей теории категорий мы могли бы.

Control.Category обобщает немного: объекты Control.Category категория C все еще являются типами [1] так же, как в Hask, но его морфизмы являются вещами типа C a b, Так что в вашем примере объекты по-прежнему являются произвольными типами, но ваши морфизмы - это вещи типа Invertible a b, Поскольку ваши морфизмы не являются функциями, вы не сможете использовать стандартные Functor классы.

Тем не менее, это забавное упражнение в создании своего ноу-хау теории категорий, чтобы определить класс функторов, который работает между Category категории, а не предполагая Hask, который захватил бы ваш пример. Помните, что функтор действует на объекты (типы) и морфизмы.

Я оставлю вас с этим - не стесняйтесь комментировать, если вы хотите больше рекомендаций.


[1] Игнорирование PolyKinds, что делает это немного более общим.

Другие вопросы по тегам