Pet*_*lák 22 haskell arrows functor category-theory profunctor
显然,每个人Arrow
都是一个Strong
教练.确实^>>
和>>^
对应lmap
和rmap
.而first'
和second'
只是同first
和second
.同样,每个人ArrowChoice
也都是Choice
.
与箭相比,影响者缺乏的是构成它们的能力.如果我们添加构图,我们会得到一个箭头吗?换句话说,如果(强)profunctor也是一个类别,它是否已经是一个箭头?如果没有,有什么遗漏?
hao*_*hao 33
与箭相比,影响者缺乏的是构成它们的能力.如果我们添加构图,我们会得到一个箭头吗?
这正是" 作为Monoids的计算概念 "第6节中解决的问题,它解析了(相当密集的)" 箭头的分类语义 "的结果."概念"是一篇很好的论文,因为虽然它深入研究范畴理论,但它(1)并不认为读者不仅仅是粗略的抽象代数知识,(2)用Haskell代码说明大多数偏头痛诱导数学.我们可以在这里简要总结一下论文的第6部分:
说我们有
class Profunctor p where
dimap :: (contra' -> contra) -> (co -> co') -> p contra co -> p contra' co'
Run Code Online (Sandbox Code Playgroud)
你在Haskell中对标准符号进行了标准的,负面和正面的dividin编码.现在这个数据类型,
data (?) f g contra co = forall x. (f contra x) ? (g x co)
Run Code Online (Sandbox Code Playgroud)
在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)
Run Code Online (Sandbox Code Playgroud)
由于时间和空间的原因,我们将手动证明它是合法的.
好.现在有趣的部分.说我们这个类型类:
class Profunctor p => ProfunctorMonoid p where
e :: (a -> b) -> p a b
m :: (p ? p) a b -> p a b
Run Code Online (Sandbox Code Playgroud)
这是一种更加挥手的方式,一种在Haskell中编码profunctor monoids概念的方法.具体地,这是在monoidal范畴幺半群Pro
,这是函子类别monoidal结构[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
Run Code Online (Sandbox Code Playgroud)
当然,我们忽略了这里的类型类法则,但正如文章所示,它们确实非常有效.
现在我说几乎是因为我们无法实施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
Run Code Online (Sandbox Code Playgroud)
对于期望的同构来说,是必要的和充分的Arrow
."强者"这个词来自于类别理论中的一个特定概念,并且本文以更好的写作和更丰富的细节来描述.
总结一下:
在一系列中,一个幺半群是一个前箭头,反之亦然.(本文的前一版本使用术语"弱箭头"而不是前箭头,我猜也是如此.)
强衍射器类别中的幺半群是箭头,反之亦然.
由于monad是endofunctor类别中的幺半群,我们可以想到SAT类比Functor : Profunctor :: Monad : Arrow
.这是计算概念作为幺半群纸的真正重点.
幺半群和幺半群类别是温和的海洋生物,无处不在,有些学生将通过计算机科学或软件工程教育而不被教授幺半群是一种耻辱.
范畴理论很有趣.
Haskell很有趣.
@ haoformayor的回答(以及参考文献)是对基础范畴理论的深刻见解 - 幺半群类别相当漂亮!- 但我认为一些代码向您展示了如何将它们Arrow
变成a Strong Category
,反之亦然,因为它们出现在各自的库中可能会成为一个有用的附录.
import Control.Arrow
import Control.Category
import Data.Profunctor
import Data.Profunctor.Strong
import Prelude hiding (id, (.))
Run Code Online (Sandbox Code Playgroud)
单程...
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
Run Code Online (Sandbox Code Playgroud)
......还有......
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
Run Code Online (Sandbox Code Playgroud)