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

Как неучтенные и фэннины связаны в теории категорий?

В библиотеке, которую я пишу, я считаю, что было бы элегантно писать класс, похожий на (но немного более общий) следующий, который объединяет как обычные uncurry над продуктами, так и fanin (от здесь или здесь, если вы предпочитаете):

{-# LANGUAGE TypeOperators, TypeFamilies,MultiParamTypeClasses, FlexibleInstances #-}
import Prelude hiding(uncurry)
import qualified Prelude 

class Uncurry t r where
    type t :->-> r
    uncurry :: (t :->-> r) -> t -> r

instance Uncurry () r where
    type () :->-> r = r
    uncurry = const

instance Uncurry (a,b) r where
    type (a,b) :->-> r = a -> b -> r
    uncurry = Prelude.uncurry

instance (Uncurry b c, Uncurry a c)=> Uncurry (Either a b) c where
    type Either a b :->-> c = (a :->-> c, b :->-> c)
    uncurry (f,g) = either (uncurry f) (uncurry g)

Обычно я просматриваю пакет Edward Kmett categories (связанный выше), чтобы понять мои вещи, но в этом пакете у нас есть фаны и недра, разделенные соответственно на классы CoCartesian и CCC.

Я немного читал о BiCCCs, но пока не понимаю их.

Мои вопросы

  • Является ли абстракция выше оправданной каким-то образом щуриться в теории категорий?

  • Если да, то каков был бы правильный язык, основанный на CT, чтобы говорить о классе и его экземплярах?


РЕДАКТИРОВАТЬ. В случае, если это поможет, и упрощение выше искажает вещи: в моем фактическом приложении я работаю с вложенными продуктами и копроизведениями, например. (1,(2,(3,()))). Вот реальный код (хотя по скучным причинам последний экземпляр упрощается и не работает отдельно, как написано)

instance Uncurry () r where
    type () :->-> r = r
    uncurry = const

instance (Uncurry bs r)=> Uncurry (a,bs) r where
    type (a,bs) :->-> r = a -> bs :->-> r
    uncurry f = Prelude.uncurry (uncurry . f)

-- Not quite correct
instance (Uncurry bs c, Uncurry a c)=> Uncurry (Either a bs) c where
    type Either a bs :->-> c = (a :->-> c, bs :->-> c)
    uncurry (f,fs) = either (uncurry f) (uncurry fs) -- or as Sassa NF points out:
                                                     -- uncurry (|||)

Итак, экземпляр const для экземпляра () пришел естественным образом как рекурсивный базовый случай для экземпляра n-ary tuple uncurry, но все три вместе выглядели как что-то не произвольное.


Обновление

Я обнаружил, что мышление в терминах алгебраических операций, a.la Chris Taylor блоги об "алгебре ADT" . Сделав это, я разъяснил, что мой класс и методы - это действительно законы экспоненты (и причина, почему мой последний пример был неправильным).

Вы можете увидеть результат в моем пакете shapely-data, в классах Exponent и Base; см. также источник заметок и разметку неаккуратного документа.

4b9b3361

Ответ 1

Ваш последний экземпляр Uncurry - это именно uncurry (|||), поэтому в нем нет ничего более общего.

Карри находит для любой стрелки f: A & times; B → C a curry f: A → C B так что уникальная стрелка eval: C B & times; B & C коммутирует. Вы можете просмотреть eval как ($). Высказывание "CCC" является сокращением для "в этой категории мы имеем все продукты, все экспоненты и терминальный объект" - другими словами, currying работает для любой пары типов и любой функции в haskell. Одним из важных следствий существования CCC является то, что A = 1 & times; A = A & times; 1 (или a изоморфно (a,()) и изоморфно ((),a)).

Нераспространение в haskell - это противоположная маркировка того же процесса. Начнем со стрелки f = uncurry g. Каждая пара имеет два проекции, поэтому композиция proj 1 и curry f= g дает C B. Поскольку мы говорим о составе и продуктах, неучтенное в CCC определяет уникальное uncurry g для любого g: A → C B. В CCC у нас есть все продукты, поэтому мы имеем C B & times; B, которые можно охарактеризовать на C.

В частности, вспомним A = A & times; 1. Это означает, что любая функция A → B также является функцией A & times; 1 → B. Вы также можете рассматривать это как "для любой функции A → B существует функция A & times; 1 → B", доказанная тривиальным неуправляемым, из которых ваш первый экземпляр делает только половину (это доказывает только для id).

Я бы не назвал последний экземпляр "неустранимым" в том же смысле, что и определение карри. Последний пример представляет собой конструкцию определения копродукта - для любой пары стрелок f: A → C и g: B → C имеется уникальная стрелка [f, g]: (A + B) → C. В этом смысле это выглядит как злоупотребление интерфейсом - это обобщение смысла от "неоткуда", чтобы "что-то дать, дать мне что-то" или "истинное соответствие между :->-> и функциями haskell". Возможно, вы можете переименовать класс в Arrow.