Там нет никаких ограничений на всех! Когда я начал изучать теоретико-категорийную основу для конструкторов типов, этот момент меня и смутил. Мы доберемся до этого. Но сначала позвольте мне прояснить некоторую путаницу. Эти две цитаты:
такой функтор может иметь только в качестве целевой категории категорию, созданную с использованием конструктора типа
и
можно думать о функторах, имеющих любую категорию как цель функтора, например, категорию всех типов Haskell
покажите, что вы неправильно понимаете, что такое функтор (или, по крайней мере, вы неправильно используете терминологию).
Функторы не сооружать категории. Функтор - это отображение между категориями. Функторы переносят объекты и морфизмы (типы и функции) в исходной категории к объекту и морфизмы в целевой категории.
Обратите внимание, что это означает, что функтор - это действительно пара отображений: отображение объектов F_obj и отображение морфизмов F_morph . В Haskell объектная часть F_obj функтора - это имя конструктора типа (например List
), в то время как часть морфизма - это функция fmap
(компилятор Haskell должен разобраться, на что fmap
мы ссылаемся в любом данном выражении). Таким образом, мы не можем сказать, что List
это функтор; только комбинация List
и fmap
является функтором. Тем не менее, люди злоупотребляют нотацией; программисты вызывают List
функтор, в то время как теоретики категорий используют один и тот же символ для ссылки на обе части функтора.
Кроме того, в программировании почти все функторы являются эндофункторами , то есть исходная и целевая категории одинаковы - категория всех типов в нашем языке. Давайте назовем эту категорию типом . Endofunctor F в Type отображает тип T в другой тип FT, а функцию T -> S в другую функцию FT -> FS . Это отображение должно, конечно, подчиняться законам функторов.
В List
качестве примера: у нас есть конструктор типа List : Type -> Type
и функция fmap: (a -> b) -> (List a -> List b)
, которые вместе образуют функтор. T
Есть один последний момент, чтобы прояснить. Запись List int
не создает новый тип списков целых чисел. Этот тип уже существовал . Это был объект в нашей категории Type . List Int
это просто способ сослаться на это.
Теперь вам интересно, почему функтор не может сопоставить тип, скажем, Int
или String
. Но это может! Нужно просто использовать функтор идентичности. Для любой категории C функтор идентичности отображает каждый объект на себя и морфизм на себя. Нетрудно убедиться, что это отображение удовлетворяет законам функторов. В Haskell это будет конструктор типов, id : * -> *
который отображает каждый тип на себя. Например, id int
оценивает до int
.
Более того, можно даже создавать постоянные функторы, которые отображают все типы в один тип. Например, функтор ToInt : * -> *
, где ToInt a = int
для всех типов a
, и отображает все морфизмы в целочисленную функцию идентичности: fmap f = \x -> x