gpt4 book ai didi

haskell - Haskell 中常见的 monad 对应的伴随仿函数对是什么?

转载 作者:行者123 更新时间:2023-12-03 00:01:53 26 4
gpt4 key购买 nike

在范畴论中,单子(monad)可以由两个伴随仿函数构造而成。特别是,如果CD是类别,并且F : C --> DG : D --> C 是伴随仿函数,即存在双射

hom(FX,Y) = hom(X,GY)

对于C中的每个XD中的Y,则组合G o F: C --> C 是一个单子(monad)。

<小时/>

可以通过固定类型 b 并取 FG 来给出一对这样的伴随仿函数

data F b a = F (a,b)
data G b a = G (b -> a)

instance Functor (F b) where
fmap f (F (a,b)) = F (f a, b)

instance Functor (G b) where
fmap f (G g) = G (f . g)

并且 hom-sets 之间的双射是通过柯里化(Currying)给出的(模构造函数):

iso1 :: (F b a -> c) -> a -> G b c
iso1 f = \a -> G $ \b -> f (F (a,b))

iso2 :: (a -> G b c) -> F b a -> c
iso2 g = \(F (a,b)) -> let (G g') = g a in g' b

在这种情况下对应的 monad 是

data M b a = M { unM :: b -> (a,b) }

instance Monad (M b) where
return a = M (\b -> (a,b))
(M f) >>= g = M (\r -> let (a,r') = f r in unM (g r') a)

我不知道这个 monad 的名字应该是什么,除了它似乎是一个类似阅读器 monad 的东西,它携带着一段可重写的信息(编辑: dbaupp 点在评论中指出这是 State monad。)

因此,State 单子(monad)可以“分解”为一对伴随仿函数 FG,我们可以这样写

State = G . F

到目前为止,一切顺利。

<小时/>

我现在正在尝试弄清楚如何将其他常见单子(monad)分解为成对的伴随仿函数 - 例如 Maybe[]Reader code>、WriterCont - 但我无法弄清楚我们可以将它们“分解”成的伴随仿函数对是什么。

唯一简单的情况似乎是Identity monad,它可以分解为任何一对仿函数FG,这样FG 相反(特别是,您可以只采用 F = IdentityG = Identity)。

有人可以透露一些信息吗?

最佳答案

您正在寻找的是 Kleisli category 。它最初的开发是为了表明每个单子(monad)都可以由两个伴随仿函数构建。

问题是 Haskell Functor不是通用仿函数,它是 Haskell 类别中的内仿函数。因此,我们需要一些不同的东西(据我所知)来表示其他类别之间的仿函数:

{-# LANGUAGE FunctionalDependencies, KindSignatures #-}
import Control.Arrow
import Control.Category hiding ((.))
import qualified Control.Category as C
import Control.Monad

class (Category c, Category d) => CFunctor f c d | f -> c d where
cfmap :: c a b -> d (f a) (f b)

请注意,如果我们取 ->对于两者cd我们得到一个 Haskell 范畴的内仿函数,它就是 fmap 的类型。 :

cfmap :: (a -> b) -> (f a -> f b)

现在我们有了显式类型类,它表示两个给定类别之间的仿函数 cd我们可以表达给定单子(monad)的两个伴随仿函数。左边映射一个对象a到只是a并映射态射 f(return .) f :

-- m is phantom, hence the explicit kind is required
newtype LeftAdj (m :: * -> *) a = LeftAdj { unLeftAdj :: a }
instance Monad m => CFunctor (LeftAdj m) (->) (Kleisli m) where
cfmap f = Kleisli $ liftM LeftAdj . return . f . unLeftAdj
-- we could also express it as liftM LeftAdj . (return .) f . unLeftAdj

右侧映射一个对象a反对m a并映射态射 gjoin . liftM g ,或相当于 (=<<) g :

newtype RightAdj m a = RightAdj { unRightAdj :: m a }
instance Monad m => CFunctor (RightAdj m) (Kleisli m) (->) where
cfmap (Kleisli g) = RightAdj . join . liftM g . unRightAdj
-- this can be shortened as RightAdj . (=<<) g . unRightAdj

(如果有人知道如何在 Haskell 中表达这一点的更好方法,请告诉我。)

关于haskell - Haskell 中常见的 monad 对应的伴随仿函数对是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13937289/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com