Где бифунктор для функций в haskell?

Я не могу найти бифункторный аналог fmap.

Объяснение:

Функтор для объектов - конструктор типа данных. Тип 1_

Функтор для функций - fmap. Тип - (a -> b) -> (fa -> fb)

Бифунктор для объектов - результат bimap f g, где f :: (a -> a'), g :: (b -> b'). Тип - p a b -> p a' b'

Бифунктор для функций — ?. Тип - p (a -> b) (c -> d) -> p (a' -> b') (c' -> d')

Вот почему я думаю, что бифунктор имеет такой тип (я прав?) с некоторым примером

введите здесь описание изображения


ОБНОВИТЬ

введите здесь описание изображения


ОБНОВЛЕНИЕ2

p (a -> b) (c -> d) -> p (a' -> b') (c' -> d') на изображении выше — это морфизм бифунктора в бифунктор, а также профунктор (поскольку все функции являются профункторами)

Резюме:

Я думал, что p (a -> b) (c -> d) -> p (a' -> b') (c' -> d') — это бифунктор для функций, но это не так. Бифунктор для морфизмов bimap. Type: (a -> b) -> (α -> β) -> p a α -> p b β.

Я думал p (a -> b) (c -> d) -> p (a' -> b') (c' -> d') что-то необычное, но это не так, это просто функция


person srghma    schedule 18.07.2018    source источник
comment
Функция — это профунктор, она контравариантна по аргументу (contramap) и ковариантна по возвращаемому типу (fmap). Он называется dimap: dimap :: (a -> b) -> (c -> d) -> p b c -> p a d. Для типа стрелки: (a -> b) -> (c -> d) -> (b -> c) -> a -> d (hackage.haskell .org/package/profunctors-5.3/docs/)   -  person Yuval Itzchakov    schedule 18.07.2018
comment
@YuvalItzchakov, следуя моему примеру, как получить функцию с типом (Int, Float) -> (Id Int, Id2 Float), используя dimap?   -  person srghma    schedule 18.07.2018
comment
Я думаю, что название может немного ввести в заблуждение, если я правильно вас понимаю. Я думаю, вы говорите: у любого функтора есть две части: часть уровня типа (вы называете ее функтором для объектов, но я бы определенно предложил сказать уровень типа) и часть уровня значения (которая fmap) и что вы спрашиваете, что такое часть бифунктора на уровне значений. Это то, что вы спрашиваете? (Кстати, если это так, функтор для части объектов неверен. Он находится на уровне типа, и вы говорите о конструкторах данных, которые являются уровнем значений, если я правильно интерпретирую).   -  person David Young    schedule 18.07.2018
comment
Прочитав его еще раз, я немного менее уверен, что правильно понял вопрос раньше. Может быть, вы могли бы немного перефразировать? Что конкретно вы подразумеваете под всеми упомянутыми вами вещами (например, что такое Id и Id2 и какое отношение имеет подпись типа p (a -> b) (c -> d) -> p (a' -> b') (c' -> d') к остальной части того, о чем вы спрашиваете)?   -  person David Young    schedule 18.07.2018
comment
@DavidYoung re what relation - это на картинке   -  person srghma    schedule 18.07.2018
comment
в начале вашего поста я ожидаю, что второе предложение будет следовать за первым, как бифунктор для объектов - конструктор типа данных. Тип 1_. Бифунктор для функций - bimap. Тип - (a -> b) -> (c -> d) -> (p a c -> p b d).   -  person Will Ness    schedule 18.07.2018
comment
@WillNess, может быть, ты прав, фраза all products and coproducts are bifunctors говорит о том, что ты прав. Тогда мой график неверен   -  person srghma    schedule 18.07.2018


Ответы (2)


Функтор для объектов - конструктор типа данных. Тип 1_

Функтор для функций - fmap. Тип - (a -> b) -> (fa -> fb)

Хотя в целом это имеет смысл, важно понимать, что стрелки выше имеют три разных значения.

Функтор для объектов - конструктор типа данных. Тип - a ⟼ f a

Функтор для функций - fmap. Тип - (a ⟿ b) ⟶ (f a ⟿ f b)

куда

  • — это «символ отображения на уровне типа», который связывает тип a с типом f a. Это не имеет ничего общего с функциями уровня значения, домен которых a, а кодовый домен f a. (Они встречаются в аппликативах/монадах, но это совсем другая история.)
  • — конструктор типа для некоторого морфизма. В категории Hask эти морфизмы являются функциями Haskell, но это всего лишь частный случай.
  • — это фактический конструктор функционального типа.

Вы можете пока забыть о различиях между последними двумя, но и действительно концептуально совершенно разные. По сути, похож на стрелку, которую вы пишете в лямбде.

Maybe :: Type -> Type
Maybe = \a ⟼ Maybe a

тогда как - это просто способ выразить, что вы абстрагируетесь от функциональных вещей.

Другая связанная с этим вещь, которая может быть неясна, заключается в том, что объекты, о которых вы говорите, являются типами Haskell. Не значения (как объектно-ориентированные объекты).

Итак, я бы сформулировал список, который вы привели выше, следующим образом:

  • Функтор

    • for objects: datatype constructor. Kind Type -> Type, mapping-association a ⟼ f a.
    • для морфизмов: fmap. Тип: (a -> b) -> (f a -> f b).
  • бифунктор

    • for objects: datatype constructor. Kind Type×Type -> Type, or curried Type -> Type -> Type, mapping-association a ⟼ b ⟼ p a b.
    • для морфизмов: bimap. Тип: (a -> b) -> (α -> β) -> p a α -> p b β.

На самом деле в Haskell нет или того, что вы написали с помощью a -> f a. Это будет лямбда-выражение уровня типа, но на самом деле функции уровня типа могут быть выражены только как семейства типов, т. е. ближе всего к выражению a ⟼ f a можно получить type instance Functored a = f a.

person leftaroundabout    schedule 18.07.2018
comment
@WillNess на самом деле скопировано из вопроса. Не уверен, что это было сделано намеренно; в этот момент может иметь смысл рассматривать f a как «атомарный» тип. Но, не так уж много смысла, я думаю, что я изменю это. - person leftaroundabout; 18.07.2018
comment
Я обновил изображение, но я все еще не понимаю, как p (a -> b) (c -> d) -> p (a' -> b') (c' -> d') является профунктором, особенно когда p является (,). Следуя моему примеру, как получить функцию с типом (Int, Float) -> (Id Int, Id2 Float), используя dimap - person srghma; 18.07.2018
comment
@srghma функторы имеют fmap ( [x]-f- ), бифункторы есть bimap ( [x,y]-(f,g)- ), профункторы имеют dimap ( -f-[x-y]-g- ). - person Will Ness; 18.07.2018
comment
@WillNess Извините, предыдущий комментарий должен был быть написан так: я обновил изображение, но я до сих пор не понимаю, как морфизм на моем втором рассматриваемом изображении, имеющем тип p (a -> b) (c -> d) -> p (a' -> b') (c' -> d'), является профунктором (как указал @YuvalItzchakov) , особенно когда p равно (,). На изображении, о котором идет речь, я привел примеры для некоторых частей графика. Следуя этим примерам, этот морфизм должен иметь тип (Int, Float) -> (Id Int, Id2 Float), но я не понимаю, как получить этот тип, используя dimap - person srghma; 18.07.2018
comment
@srghma вы делаете это, используя бимап, как показывает ответ Чепнера. сами функции можно рассматривать как профункторы или использовать для реализации бифункторного (например) поведения, например, с bimap. (IOW, вы можете игнорировать этот комментарий, я думаю, что он здесь не актуален.) - person Will Ness; 18.07.2018
comment
@WillNess хорошо, он сказал это о функциях в целом, а не об этом конкретном морфизме. Этот морфизм также строится с использованием bimap. спасибо - person srghma; 18.07.2018

Вам не нужен экземпляр Bifunctor для (->), достаточно (,):

b1 :: a -> Id a
b2 :: a -> Id2 a

-- instance Bifunctor (,) where
--   bimap f g (x, y) = (f x, g y)

f :: (Int, Float) -> (Id Int, Id2 Float)
f = bimap b1 b2
person chepner    schedule 18.07.2018