显然,每个Arrow
都是Strong
发送者。确实^>>
和>>^
对应lmap
和rmap
。 first'
和second'
与first
和second
相同。同样,每个ArrowChoice
也是Choice
。
与箭相比,影响者缺乏的是构成它们的能力。如果我们添加构图,我们会得到一个箭头吗?换句话说,如果(强)profunctor也是category,它是否已经是箭头?如果不是,缺少什么?
答案 0 :(得分:30)
与箭相比,影响者缺乏的是构成它们的能力。如果我们添加构图,我们会得到一个箭头吗?
这正是“Notions of Computation as Monoids”第6节中解决的问题,它解析了(相当密集的)“Categorical semantics for arrows”的结果。 “概念”是一篇很好的论文,因为虽然它深入研究范畴理论,但它(1)并不认为读者不仅仅是粗略的抽象代数知识,(2)用Haskell代码说明大多数偏头痛诱导数学。我们可以在这里简要总结一下论文的第6部分:
说我们有
class Profunctor p where
dimap :: (contra' -> contra) -> (co -> co') -> p contra co -> p contra' co'
你在Haskell中对标准符号进行了标准的,负面和正面的dividin'编码。现在这个数据类型,
data (⊗) f g contra co = forall x. (f contra x) ⊗ (g x co)
在Data.Profunctor.Composition中实现的就像profunctor的组合一样。例如,我们可以展示一个合法的实例Profunctor
:
instance (Profunctor f, Profunctor g) => Profunctor (f ⊗ g) where
dimap contra co (f ⊗ g) = (dimap contra id f) ⊗ (dimap id co g)
由于时间和空间的原因,我们将手动证明它是合法的。
行。现在有趣的部分。假设我们这个类型类:
class Profunctor p => ProfunctorMonoid p where
e :: (a -> b) -> p a b
m :: (p ⊗ p) a b -> p a b
这更像是挥手致意,是一种在Haskell中编码profunctor monoids概念的方法。具体来说,这是幺半群类Pro
中的幺半群,它是函数类[C^op x C, Set]
的幺半群结构,其中⊗
为张量,Hom
为其单位。所以这里有很多非特异性的数学用法,但是你应该阅读这篇论文。
然后我们看到ProfunctorMonoid
与Arrow
几乎是同构的......差不多。
instance ProfunctorMonoid p => Category p where
id = dimap id id
(.) pbc pab = m (pab ⊗ pbc)
instance ProfunctorMonoid p => Arrow p where
arr = e
first = undefined
instance Arrow p => Profunctor p where
lmap = (^>>)
rmap = (>>^)
instance Arrow p => ProfunctorMonoid p where
e = arr
m (pax ⊗ pxb) = pax >> pxb
当然,我们忽略了这里的类型类法则,但正如文章所示,它们确实很有效。
现在我说几乎是因为我们无法实现first
。我们真正做的是证明了ProfunctorMonoid
和前箭头之间的同构。本文调用了Arrow
而没有first
前箭头。然后它继续显示
class Profunctor p => StrongProfunctor p where
first :: p x y -> p (x, z) (y, z)
class StrongProfunctor p => StrongProfunctorMonoid p where
e :: (a -> b) -> p a b
m :: (p ⊗ p) a b -> p a b
对Arrow
所需的同构是必要且充分的。 “强”这个词来自于类别理论中的一个特定概念,并且在论文中以更好的写作和更丰富的细节来描述。
总结一下:
“精灵”类别中的幺半群是前箭头,反之亦然。 (该论文的前一版本使用术语“弱箭头”而不是前箭头,我猜也是如此。)
强健身分类中的幺半群是箭头,反之亦然。
由于monad是endofunctor类别中的monoid,我们可以想到SAT类比Functor : Profunctor :: Monad : Arrow
。这是计算概念作为幺半群纸的真正重点。
幺半群和幺半群是温和的海洋生物,无处不在,有些学生在没有被教授幺半群的情况下会通过计算机科学或软件工程教育,这是一种耻辱。
分类理论很有趣。
Haskell很有趣。
答案 1 :(得分:6)
@ haoformayor的回答(以及参考文献)是对基础范畴理论的深刻见解 - 幺半群类别相当漂亮! - 但是我想一些代码向您展示如何将Arrow
变成Strong Category
,反之亦然,因为它们出现在各自的图书馆中可能会作为一个有用的附录。
import Control.Arrow
import Control.Category
import Data.Profunctor
import Data.Profunctor.Strong
import Prelude hiding (id, (.))
单程......
newtype WrapP p a b = WrapP { unwrapP :: p a b }
instance Category p => Category (WrapP p) where
id = WrapP id
WrapP p . WrapP q = WrapP (p . q)
instance (Category p, Strong p) => Arrow (WrapP p) where
first = WrapP . first' . unwrapP
second = WrapP . second' . unwrapP
-- NB. the first usage of id comes from (->)'s Category instance (id :: a -> a)
-- but the second uses p's instance (id :: p a a)
arr f = WrapP $ dimap f id id
......和其他......
newtype WrapA p a b = WrapA { unwrapA :: p a b }
instance Arrow p => Profunctor (WrapA p) where
dimap f g p = WrapA $ arr f >>> unwrapA p >>> arr g
instance Arrow p => Strong (WrapA p) where
first' = WrapA . first . unwrapA
second' = WrapA . second . unwrapA