Как функторы в Haskell связаны с функторами в теории категорий?
Насколько я понимаю, функтор - это отображение между двумя категориями, например, от объектов в
к объектам в
, где
и
являются категориями.
В Haskell есть Hask, в котором объекты являются типами Haskell, а морфизмы являются функциями Haskell. Однако класс типов Functor
имеет функцию fmap
, которая сопоставляет эти типы (которые, таким образом, являются объектами, а не самими категориями):
fmap :: (a -> b) -> f a -> f b
f a
и f b
являются объектами в Hask. Означает ли это, что каждый экземпляр Functor
в Haskell является endofunctor, и если нет, то Functor
действительно представляет функтор?
Что мне здесь не хватает? Являются ли типы также категориями в Haskell?
Ответы
Ответ 1
Экземпляр Functor
указывает две вещи: конструктор типа F
вида * -> *
, то есть отображение объектов объекта Hask в объекты Hask и функцию типа (a -> b) -> (F a -> F b)
, то есть, отображение из стрелок Hask в стрелки Hask, совместимое с отображением объектов F
. Итак, да, все экземпляры Functor
являются endofunctors. В Hackage имеется несколько обобщений. Control.Categorical.Functor.
Ответ 2
Да, все экземпляры Functor
являются endofunctors на Hask - на самом деле, endofunctors из всех Hask для правильной подкатегории, объектами которой являются типы, полученные применением конкретный конструктор типов. Этот конструктор типов - это то, с чем связан экземпляр Functor
, и дает отображение для объектов; отображение для морфизмов fmap
, которое (поскольку мы имеем дело только с эндофенторами на декартовой замкнутой категории) само является семейством морфизмов в Hask.
Имеет смысл рассматривать другие функторы, кроме тех, которые могут иметь экземпляры Functor
, такие как контравариантные функторы (от Hask в свою противоположную категорию). Функция arr
в класс Arrow
также соответствует функтору, от всех Hask до категории объекты которого совпадают с объектами Hask и морфизмы которых описываются конструктором типа, с которым связан экземпляр Arrow
.
Возможны дальнейшие обобщения (как отмечает Даниэль Вагнер), но они становятся все более неудобными в использовании.
Ответ 3
Одним из важных моментов в этом является то, что вам действительно нужны функции обогащенные в Hask, а не просто старые функторы. Hask является декартовым закрытым (не совсем, но он старается изо всех сил), и поэтому он, естественно, обогащен сам.
Теперь обогащенные endofunctors дают вам возможность ограничить возможности, реализуемые внутри языка: обогащенный функтор Hask → Hask - это функция на уровне объектов (типов) f a
и для каждая пара объектов a, b
морфизм в Hask, идущий f: Hask (a, b) → Hask (fa, fb). Конечно, это просто fmap :: (a -> b) -> f a -> f b