Monads作为附件

我一直在阅读有关monad的分类理论。 单子的一个定义使用一对伴随函数。 monad通过使用这些函子的往返来定义。 显然助理在类别理论中非常重要,但我从来没有在伴随函数方面看到任何Haskell单子的解释。 有没有人给过它一个想法?


编辑 :只是为了好玩,我会正确地做到这一点。 原始答案保存在下面

现在,类别附加组件的当前附加代码位于附件包中:http://hackage.haskell.org/package/adjunctions

我只是明确而简单地通过状态monad。 此代码使用来自变压器包的Data.Functor.Compose ,但是它是自包含的。

f(D→C)和g(C→D)之间的一个连接点写成f - | g,可以用多种方法表征。 我们将使用counte / unit(epsilon / eta)描述,它给出了两个自然变换(仿函数之间的态射)。

class (Functor f, Functor g) => Adjoint f g where
     counit :: f (g a) -> a
     unit   :: a -> g (f a)

请注意,议会中的“a”实际上是C中的身份函子,单位中的“a”实际上是D中的身份函子。

我们也可以从coun / unit定义中恢复hom-set的附属定义。

phiLeft :: Adjoint f g => (f a -> b) -> (a -> g b)
phiLeft f = fmap f . unit

phiRight :: Adjoint f g => (a -> g b) -> (f a -> b)
phiRight f = counit . fmap f

无论如何,我们现在可以从我们的单位/议会联盟中定义Monad,如下所示:

instance Adjoint f g => Monad (Compose g f) where
    return x = Compose $ unit x
    x >>= f  = Compose . fmap counit . getCompose $ fmap (getCompose . f) x

现在我们可以实现(a,)和(a - >)之间的经典连接:

instance Adjoint ((,) a) ((->) a) where
    -- counit :: (a,a -> b) -> b
    counit (x, f) = f x
    -- unit :: b -> (a -> (a,b))
    unit x = y -> (y, x)

现在是一个类型的同义词

type State s = Compose ((->) s) ((,) s)

如果我们用ghci加载它,我们可以确认这个状态正是我们经典的状态monad。 请注意,我们可以采取相反的构图,并获得Costate Comonad(又名商店comonad)。

我们可以用这种方式将其他一些附加元素制作成monad(比如(Bool,Pair)),但它们有点奇怪。 不幸的是,我们无法以愉快的方式直接在Haskell中引发Reader和Writer。 我们可以做Cont,但是正如copumpkin所描述的那样,它需要来自相反类别的一个连接,所以它实际上使用了“Adjoint”类型类型的一个不同的“形式”,以反转一些箭头。 这种形式也在辅助包中的不同模块中实现。

Derek Elkins的文章“Monad Reader 13 - 用分类理论计算Monad:http://www.haskell.org/wikiupload/8/85/TMR-Issue13.pdf”中的文章以不同的方式介绍了此材料。

此外,Hinze最近的Kan扩展程序优化论文从MonSet之间的连接中逐步构建了list monad:http://www.cs.ox.ac.uk/ralf.hinze/Kan.pdf


老答案:

两个参考。

1)类别附加服务像往常一样提供辅助表示,以及monad如何从中产生。 像往常一样,用文件思考是很好的,但很重要:http://hackage.haskell.org/packages/archive/category-extras/0.53.5/doc/html/Control-Functor-Adjunction.html

2)-Cafe还提供了一个有前途但简短的讨论副作用的讨论。 其中一些可能有助于解释类别附加说明:http://www.haskell.org/pipermail/haskell-cafe/2007-December/036328.html


Derek Elkins最近在晚餐中向我展示了Cont Monad如何由自己构造(_ -> k)逆变函子而产生,因为它恰好是自伴随的。 这就是你从(a -> k) -> k中得到的。 然而,它的议会导致双重否定消除,这在Haskell中是不能写的。

有关说明和证明这一点的一些Agda代码,请参阅http://hpaste.org/68257。


这是一个古老的线索,但我发现这个问题很有趣,所以我自己做了一些计算。 希望巴托斯仍然在那里,可能会读这..

事实上,Eilenberg-Moore建筑在这种情况下确实给出了非常清晰的图像。 (我将使用带有Haskell语法的CWM符号)

假设T是列表monad < T,eta,mu >eta = returnmu = concat ),并考虑T代数h:T a -> a

(请注意, T a = [a]是一个自由幺半群<[a],[],(++)> ,即identity []和multiplication (++) 。)

根据定义, h必须满足hT h == h.mu ah.eta a== id

现在,一些简单的追图证明了h实际上在(由x*y = h[x,y]定义的)上诱导出一个幺半群结构,并且h成为这个结构的幺半群同态。

相反,在Haskell中定义的任何幺半群结构< a,a0,* >自然被定义为T代数。

通过这种方式( h = foldr ( * ) a0 ,这个函数用(*) '替换' (:)并将[]映射到a0 )。

因此,在这种情况下,T代数的范畴只是Haskell,HaskMon中可定义的幺半群结构范畴。

(请检查T-algebras中的态射实际上是幺半同态。)

它还将HasksMon中的列表表示为通用对象,就像Grp中的免费产品,CRng中的多项式环等一样。

对应于上述结构的辅助是< F,G,eta,epsilon >

哪里

  • F:Hask -> HaskMon ,其类型为' a '生成的自由monoid,即[a]
  • G:HaskMon -> Hask ,健忘函数(忘记乘法),
  • eta:1 -> GF ,由x::a -> [x]定义的自然转换,
  • epsilon: FG -> 1 ,由上面折叠函数定义的自然变换(从一个自由幺半群到它的商幺半群的'正则投影')
  • 接下来,还有另一个'Kleisli类别'和相应的附件。 您可以检查它是否只是具有态射a -> T b的Haskell类型的类别,其组成由所谓的'Kleisli组合' (>=>) 。 一个典型的Haskell程序员会发现这个类别更熟悉。

    最后,正如CWM所示,T-代数的范畴(或Kleisli范畴)在合适的意义上成为定义列表单子T的范畴中的终端(或初始)对象。

    我建议为二叉树函子T a = L a | B (T a) (T a)做一个类似的计算 T a = L a | B (T a) (T a)检查你的理解。

    链接地址: http://www.djcxy.com/p/47689.html

    上一篇: Monads as adjunctions

    下一篇: Java: using a RuntimeException to escape from a Visitor