什么是对应于哈斯克尔单子常见的伴随函子对?(What are the adjoint functor

2019-08-04 07:08发布

在范畴论,一个单子可以从两个伴随函子来构建。 具体地,如果Cd是类和F:C - > dG:d - > C是伴随函子,在这个意义上,有一个双射

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

一种在CY各自Xd则组合物G.华氏度:C - > C是单子。


一种这样的一对伴随函子可以通过固定式给出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-集之间的双射由讨好给出(模构造函数):

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

在这种情况下相应的单子是

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)

我不知道这个单子的名称应该是什么,但它似乎像一个读者单子,围绕一块过写信息( 编辑:dbaupp在评论中指出,这是State单子。)

因此, State单子可以“分解”为一对伴随函子FG ,我们可以写

State = G . F

到现在为止还挺好。


现在,我试图找出如何分解等常见单子到伴随函子的对-例如Maybe[] ReaderWriterCont -但我想不出什么对伴随函子的,我们可以“分解”他们进入ARE。

唯一的简单情况似乎是Identity单子,它可以被分解成任何对函子FG使得F是逆G (在尤其,可以只取F = IdentityG = Identity )。

任何人都可以提供一些线索?

Answer 1:

什么你要找的是Kleisli类别 。 它最初被开发,以显示每一个单子可以从两个伴随函子来构建。

问题是,哈斯克尔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 ,我们可以表达对一个给定的单子两个伴随函子。 左边的一个对象映射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到对象ma和映射一个态射gjoin . liftM g join . 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来表达这一点,请让我知道。)



Answer 2:

  • Maybe来自于自由进入函子尖头套类别和健忘函子回
  • []来自自由算符成类群的类别和健忘函子背面

但无论这些类别都是Hask的子类别。



Answer 3:

当你观察,每对伴随函子的产生了一个单子。 反过来也成立:每个单子以这种方式出现。 事实上,这样做有两种典型方式。 一个是Kleisli建设切赫介绍; 另一种是Eilenberg摩尔定律建设。 事实上,Kleisli是初始这样的方式和EM的终端之一,在对伴随函子的合适的类别。 他们在1965年各自独立发现如果你想的细节,我强烈推荐Catsters视频 。



文章来源: What are the adjoint functor pairs corresponding to common monads in Haskell?