我正在尝试将Monad的分类定义与我在其他一些教程/书籍中看到的其他一般表示/定义进行协调。
下面,我(或许有力地)试图将两个定义关闭,请指出错误并提供更正,如果需要的话
所以从Monads的定义开始
Monads只是endofunctors类别中的幺半群。
并且对endofunctors有一点了解,我假设Monad可以写为
((a->b)->Ma->Mb)->((b->c)->Mb->Mc)
LHS的“Type
”(左侧)是Mb
,RHS的类型是Mc
,所以我想我可以按如下方式编写
Mb-> (b->c)-> Mc, **which is how we define bind**
以下是我看到Monads在endofuctors类别中的看法(它们本身在Category
C中,types
'为objects
)
这有什么意义吗?
答案 0 :(得分:9)
F :: * -> *
的东西,其中有一些函数知道如何将态射(函数)注入到Hask的子类别中,函数放在{{1}上s为态射,F
为对象,F
。你所拥有的东西似乎是哈斯克的自然变革。
示例:fmap
,Maybe
,Either a
等。
现在monad也必须有2个自然变换(hask中为(,) a
)。
Functor F, Functor g => F a -> G a
或者在haskell代码中
n : Identity -> M
u : M^2 -> M
分别对应n :: Identity a -> M a -- Identity a == a
u :: M (M a) -> M a
和return
。
现在我们必须到达join
。你所拥有的绑定实际上只是>>=
,我们真正想要的是fmap
。这很容易定义为
m a -> (a -> m b) -> m b
多田!我们有单子。现在为这个幺半群的endofunctors。
在endofunctors上的幺半群将有一个仿函数作为对象和自然变换作为态射。有趣的是,两个endofunctor的产品是它们的组成。这是我们新的幺半群的Haskell代码
m >>= f = join $ f `fmap` m
这个去了
type (f <+> g) a = f (g a)
class Functor m => Monoid' m where
midentity' :: Identity a -> m a
mappend' :: (m <+> m) a -> m a
看起来很熟悉?
答案 1 :(得分:5)
定义“Monads只是endofunctors类别中的幺半群。”,虽然这是一个糟糕的起点。它来自blog post,主要是为了开个玩笑。但如果你对这种对应感兴趣,可以在Haskell中证明:
类别的外行描述是对象之间的对象和态射的抽象集合。类别之间的映射称为仿函数,并将对象映射到对象,并将态射映射到态射,并保留身份。 endofunctor 是从类别到其自身的仿函数。
{-# LANGUAGE MultiParamTypeClasses,
ConstraintKinds,
FlexibleInstances,
FlexibleContexts #-}
class Category c where
id :: c x x
(.) :: c y z -> c x y -> c x z
class (Category c, Category d) => Functor c d t where
fmap :: c a b -> d (t a) (t b)
type Endofunctor c f = Functor c c f
满足所谓naturality conditions的仿函数之间的映射称为自然变换。在Haskell中,这些是类型为(Functor f, Functor g) => forall a. f a -> g a
的多态函数。
类别C
上的 monad 有三件事(T,η,μ)
,T
是endofunctor,1
是{{1}上的身份仿函数}}。 Mu和eta是两个满足triangle identity和相关性标识的自然变换,定义为:
C
η : 1 → T
在Haskell中μ : T^2 → T
是μ
而join
是η
return
return :: Monad m => a -> m a
可以写出Haskell中Monad的分类定义:
join :: Monad m => m (m a) -> m a
可以从这些派生运算符派生出来。
class (Endofunctor c t) => Monad c t where
eta :: c a (t a)
mu :: c (t (t a)) (t a)
这是一个完整的定义,但同样您也可以证明Monad定律可以用仿函数类别表示为Monoid定律。我们可以构造这个仿函数类别,它是一个带有对象作为仿函数(即类别之间的映射)和自然变换(即仿函数之间的映射)作为态射的类别。在endofunctors类别中,所有仿函数都是同一类别之间的仿函数。
(>>=) :: (Monad c t) => c a (t b) -> c (t a) (t b)
(>>=) f = mu . fmap f
我们可以证明这会产生一个带有函子组成的类别作为态射组成:
newtype CatFunctor c t a b = CatFunctor (c (t a) (t b))
幺半群有通常的定义:
-- Note needs UndecidableInstances to typecheck
instance (Endofunctor c t) => Category (CatFunctor c t) where
id = CatFunctor id
(CatFunctor g) . (CatFunctor f) = CatFunctor (g . f)
一类仿函数的幺半群具有自然变换作为身份a和乘法运算,它结合了自然变换。可以定义Kleisli成分以满足乘法定律。
class Monoid m where
unit :: m
mult :: m -> m -> m
所以你有它“Monads只是endofunctors类别中的幺半群”,这只是来自endofunctors和(mu,eta)的monad的正常定义的“无点”版本。
(<=<) :: (Monad c t) => c y (t z) -> c x (t y) -> c x (t z)
f <=< g = mu . fmap f . g
通过一些替换,我们可以证明instance (Monad c t) => Monoid (c a (t a)) where
unit = eta
mult = (<=<)
的幺半群属性是monad自然变换的三角形和相关性图的等价陈述。
(<=<)
如果您对diagrammatic representations感兴趣,我已经写了一些关于用字符串图表示它们的内容。
答案 2 :(得分:2)
在我看来,你忽略了重要的事情:
因此,理解定义的途径如下:
建议。不要试图在Haskell中表达一切。它专为编写程序而非数学而设计。数学符号在这里更方便,因为你可以把编写器的组合写成“∘”而不会遇到类型检查器的麻烦。