Подтвердить что ты не робот

Что именно представляют собой категории, которые сопоставляются аппликативными функторами?

Я читал Аппликативные функторы, и у меня возникли трудности с согласованием несоответствия в соответствующих терминологиях теория категорий и функциональное программирование.

Хотя я просматривал различные блоги, наиболее полные ресурсы, которые я использовал для этого исследования, следующие:

В теории категорий functor является морфизмом из source в категорию target (в категории категорий). "Категория категорий" содержит набор объектов, который содержит как исходную, так и целевую категории и набор функторов, который содержит: функтор идентичности источника; функтор идентичности целевой категории; и функтор, соединяющий источник с мишенью (если категория источника совпадает с целевой категорией, а рассматриваемый функтор является тождеством, то нужен только один функтор).

В функциональном программировании аппликативные функторы описываются как пара операций:

  • pure : a -> f a
  • <*> : f ( a -> b) -> f a -> f b.

Здесь мой вопрос

В какой интерпретации разъясняется соответствие между определением функционального программирования аппликативного функтора и категориальным определением функтора?

Более конкретно, какие части кортежа (pure,<*>) соответствуют:

  • категория источников
  • целевая категория
  • категория, в которой живет функтор.
  • функтор эффект сохранения структуры на объектах категории источников
  • эффект сохранения структуры функтора на морфизмах категории источников

Примечания: Я признаю, что это может быть неполная метафора, и не может быть однозначного соответствия для каждого из понятий, о которых я говорил. Я намеренно воздержался от того, чтобы поделиться своими предположениями о кажущихся соответствиях здесь, чтобы сохранить мой вопрос простым и избежать дальнейшего смешения вопросов.

4b9b3361

Ответ 1

Перефразируя этот ответ: Аппликативные функторы являются функторами, для которых также существует естественное преобразование, которое сохраняет моноидальную структуру их исходных/целевых категорий. В случае Haskell Applicative endofunctors (поскольку их исходная и целевая категории Hask), моноидальная структура является декартовым произведением. Таким образом, для функтора Applicative существуют естественные преобразования φ: (f a, f b) -> f (a, b) и ι: () -> f (). Таким образом, мы могли бы определить Applicative как

class Functor f => Applicative' f where
    φ :: (f a, f b) -> f (a, b)
    ι :: f ()       -- it could be \() -> f (),
                    -- but \() -> ... is redundant

Это определение эквивалентно стандартным. Мы можем выразить

φ = uncurry (liftA2 (,))
  = \(x, y) -> (,) <$> x <*> y

ι = pure ()

и наоборот

pure x   = fmap (\() -> x) ι

f <*> x  = fmap (uncurry ($)) (φ (f, x))

So pure и <*> - альтернативный способ определения этого естественного преобразования.

Ответ 2

Вероятно, проще сначала рассмотреть класс Functor (который является суперклассом Applicative). Applicative соответствует "слабый моноидальный функтор", как первая работа, на которую вы ссылались. Определение Functor:

class Functor f where
  fmap :: (a -> b) -> f a -> f b

Экземпляр Functor является конструктором типа (вида * -> *). Пример: Maybe.

В категории, о которой мы говорим, относится категория Hask, которая имеет типы Haskell как объекты и (мономорфные) функции Haskell как морфизмы. Каждый экземпляр FunctorApplicative, Monad и т.д.) Является эндофункцией в этой категории, т.е. Функтором из категории в себя.

Две карты функтора - типы Haskell-типа-Haskell и функции Haskell-Haskell-функции - это конструктор типов f и функция fmap.

Например, Int и Maybe Int - оба объекта в Hask; Maybe отображает от первого к последнему. Если chr :: Int -> Char, то fmap отображает его на fmap chr :: Maybe Int -> Maybe Char. Законы Functor соответствуют категориальным функторным законам.

В случае Applicative, Functor является суперклассом, поэтому все, что я только что сказал, применимо. В этом конкретном случае вы можете реализовать fmap с помощью pure и <*> - liftA f x = pure f <*> x - так что две части функтора, которые вы искали, это f и liftA. (Но учтите, что другие формулировки Applicative не позволяют вам этого делать - в общем, вы полагаетесь на суперкласс класса Functor.)

Я не совсем понимаю, что вы здесь подразумеваете под "категорией, в которой живет функтор".

Ответ 3

Как вы задали свой вопрос, предположите, что вы ищете категорию категорий, морфизмы которых можно понимать как функторы Haskell. Тогда это были бы виды. В категории есть один объект, который *, представляющий категорию типов хэскелей. Поскольку существует только один объект, должен быть только один набор морфизмов, который является конструктором типа (вида * → *). Не каждый конструктор типов является функтором, но каждый функтор является конструктором типа. Поэтому в этом смысле его можно понимать как морфизм от * до *.

Точкой вида является, конечно, отслеживание количества аргументов в конструкторе типа. Понять это как категорию как-то искусственно, так как у него есть только один объект.

Кроме того, для объекта * нет никакого точного морфизма. Вы могли бы думать о Identity :: * -> *, но это не тождество в строгом смысле (это зависит от естественного изоморфизма, хотя у вас есть Identity :: forall a . a -> Identity a и runIdentity :: forall a . Identity a -> a). То же самое касается композиции: вам всегда нужно использовать явный изоморфизм для работы с составленными функторами (Compose/getCompose).