Класс типов для (что кажется) контравариантного функтора, реализующего инверсию функции
Допустим, у меня есть следующее
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
- все на Хаскеле Functor
s должны быть конструкторами типов - но в общей теории категорий мы могли бы.
Control.Category
обобщает немного: объекты Control.Category
категория C
все еще являются типами [1] так же, как в Hask, но его морфизмы являются вещами типа C a b
, Так что в вашем примере объекты по-прежнему являются произвольными типами, но ваши морфизмы - это вещи типа Invertible a b
, Поскольку ваши морфизмы не являются функциями, вы не сможете использовать стандартные Functor
классы.
Тем не менее, это забавное упражнение в создании своего ноу-хау теории категорий, чтобы определить класс функторов, который работает между Category
категории, а не предполагая Hask, который захватил бы ваш пример. Помните, что функтор действует на объекты (типы) и морфизмы.
Я оставлю вас с этим - не стесняйтесь комментировать, если вы хотите больше рекомендаций.
[1] Игнорирование PolyKinds
, что делает это немного более общим.