В библиотеке, которую я пишу, я считаю, что было бы элегантно писать класс, похожий на (но немного более общий) следующий, который объединяет как обычные 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; см. также источник заметок и разметку неаккуратного документа.
