Bifunctor与Arrow方法

时间:2019-07-12 17:28:41

标签: haskell typeclass arrows bifunctor

BifunctorArrow方法之间有些重叠:

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'

如果是,那是否承认功能依赖性?

2 个答案:

答案 0 :(得分:6)

Arrowcartesian closed categories或至少cartesian monoidal categories类的(有点混蛋)的前体。具体来说,对于张量积为(,)和单位元素为()的单面类。

回想一下monoidal category的特征在于张量积是bifunctor,因此ArrowBifunctor之间存在联系。

***实际上具有比您列出的更多的法律,仅库选择使用first来制定法律。这是该类的等效定义:

class (Category k, Category k') => EnhancedCategory k k' where
  arr :: k a b -> k' a b
  -- arr id ≡ id
  -- arr (f . g) = arr f . arr g
class (EnhancedCategory (->) a) => Arrow a where
  (***) :: a b c -> a b' c' -> a (b,b') (c,c')
  -- (f***id) . (g***id) ≡ (f.g)***id
  -- (id***f) . (id***g) ≡ id***(f.g)
  -- arr fst . (f***id) ≡ f . arr fst
  -- arr snd . (id***g) ≡ g . arr snd
  -- ¿ arr swap . (f***g) ≡ (g***f) . arr swap ?
  -- ((f***g)***h) . assoc ≡ assoc . (f***(g***h))
  diag :: a b (b,b)

first :: Arrow a => a b c -> a (b,d) (c,d)
first f = f***id
second :: Arrow a => a b c -> a (d,b) (d,c)
second g = id***g
(&&&) :: Arrow a => a b c -> a b d -> a b (c,d)
f&&&g = (f***g) . diag

偶然地,也可以删除arr来提升纯函数,而只给超类提供专用方法fstsndassocI call that class Cartesian。这样可以定义包含任意Haskell函数的“箭头”类别。 linear maps是一个重要的例子。

答案 1 :(得分:1)

ArrowequivalentStrong + Category

您可以选择a different notion of strength来获得a different kind of Arrow

class Category a => ArrowChoice a where
    arr :: (b -> c) -> a b c
    (+++) :: a b c -> a b' c' -> a (Either b b') (Either c c')

换句话说,笛卡尔封闭类别的张量积不必精确(,)。您可以想到的任何张量积都有对应的强度概念,每种强度都会给您相应的Arrow种类。

值得注意的是,许多词素都为StrongChoice,因此您的Foo(基本上将Strong概括为张量积p)不会具有功能依赖性。

不幸的是,Control.Arrow中的base模块将层次结构混为一谈(例如,他们的ArrowChoice具有Arrow作为超类)。