Существует небольшое совпадение между Bifunctor
и Arrow
:
class Bifunctor p where
first :: (a -> a') -> p a b -> p a' b
second :: (b -> b') -> p a b -> p a b'
bimap :: (a -> a') -> (b -> b') -> p a b -> p a' b'
class Arrow (~~>) where
...
first :: (a ~~> a') -> (a, b) ~~> (a', b)
second :: (b ~~> b') -> (a, b) ~~> (a, b')
(***) :: (a ~~> a') -> (b ~~> b') -> (a, b) ~~> (a', b')
Класс Bifunctor
поставляется с законами, полностью аналогичными законам Functor
.
Класс Arrow
поставляется с рядом законов, различных законов и несколько загадочным предупреждением о (***)
: "Обратите внимание, что это вообще не функтор". Удивительно (для меня) там только один закон о (***)
:
first f >>> arr (id *** g) = arr (id *** g) >>> first f
Экземпляр Arrow (->)
экземпляр Bifunctor (,)
точно совпадают, поэтому bimap @(,) = (***) @(->)
. Есть ли какое-то особое значение для этого? Есть ли значимые гипотетические
class Foo (~~>) p where
biFoo :: (a ~~> a') -> (b ~~> b') -> p a b ~~> p a' b'
Если так, это допускает функциональные зависимости?