【问题标题】:Bifunctor vs. Arrow methods双函子与箭头方法
【发布时间】:2019-07-12 17:28:41
【问题描述】:

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'

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

【问题讨论】:

  • 了解 Profunctor

标签: haskell typeclass arrows bifunctor


【解决方案1】:

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

回想一下,monoidal category 的特征是张量积是双函子,所以 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 就是一个重要的例子。

【讨论】:

  • 我还有很多不明白的地方,让我先问一下EnhancedCategory是什么。
  • class EnhancedCategory k k' where arr :: k a b -> k' a b。实际上我不确定这个词是成立还是我编造了新的in constrained-categories。 — 将其编辑为答案。
  • arr fst . (f***g) ≡ f . arr fst(以及后面的两个)似乎不适合 Kleisli m 箭头实例。
  • 嗯,你说得对;这实际上似乎特定于f***id(即first f)。另外,不确定交换法...
  • 所以我猜可能是一个MonoidalCategory 具有显式张量积的类。但是没有基金?
【解决方案2】:

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

值得注意的是,许多 profunctor 都是 StrongChoice,因此您的 Foo(它基本上概括了 Strong 在张量积 p 之上)没有函数依赖关系。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 2019-07-06
    相关资源
    最近更新 更多