leo*_*leo 21 monads haskell monoids kleisli
如果你想附加两个类型为(a - > mb)的函数,这样你只能得到一个相同类型的函数来追加两个结果,你可以使用Kleisli来做到这一点:
instance (Monad m, Monoid b) => Monoid (Kleisli m a b) where
mempty = Kleisli (\_ -> return mempty)
mappend k1 k2 =
Kleisli g
where
g x = do
r1 <- runKleisli k1 x
r2 <- runKleisli k2 x
return (r1 <> r2)
Run Code Online (Sandbox Code Playgroud)
但是,目前没有定义这样的实例Control.Arrow.通常,在Haskell,我怀疑有一个很好的理由,但找不到哪一个.
这个问题是相当类似,这一个.但是,使用Monoid我没有看到定义实例的方法,例如:
instance (Monad m, Monoid b) => Monoid (a -> m b) where
[...]
Run Code Online (Sandbox Code Playgroud)
因为已经存在一个实例:
instance Monoid b => Monoid (a -> b) where
[...]
Run Code Online (Sandbox Code Playgroud)
pig*_*ker 28
在图书馆设计业务中,我们在这里面临一个选择点,我们选择在集体政策(或缺乏集体政策)中不完全一致.
MonoidMonad(或Applicative)类型构造函数的实例可以以各种方式出现.逐点提升始终可用,但我们没有定义
instance (Applicative f, Monoid x) => Monoid (f x) {- not really -} where
mempty = pure mempty
mappend fa fb = mappend <$> fa <*> fb
Run Code Online (Sandbox Code Playgroud)
请注意,这instance Monoid (a -> b)只是一个逐点提升,因此(a -> m b)只要幺半群实例为幺半群提供m b逐点提升,就会发生逐点提升b.
我们一般不做逐点提升,不仅因为它会阻止Monoid其载体碰巧应用类型的其他实例,而且因为它的结构f通常被认为比那个更重要x.在点A键情况下是自由幺,更好地为[x],它是一种Monoid通过[]和(++),而不是由逐点的提升.幺半群结构来自列表包装,而不是来自包装的元素.
我的首选经验法确实优先考虑类型构造函数中固有的幺半群结构优先于点状提升,或类型特定实例的幺半群结构,如幺半群的组合a -> a.这些可以而且确实得到了newtype包装.
争论是否Monoid (m x)应该与MonadPlus m两者都存在(并且类似地Alternative)相吻合.我的感觉是唯一的好MonadPlus例子是一个实例的副本Monoid,但其他的不同.尽管如此,图书馆在这个问题上仍然不一致,特别是在这个问题上(很多读者都会看到我的这个古老的虫子来了)......
... monoid实例Maybe,它忽略了我们经常Maybe用来模拟可能的失败的事实,而是观察到在一个额外的元素中夹持相同的数据类型的想法可以用来给半群一个中性元素,如果它没有'已经有一个.这两种结构产生了同构类型,但它们在概念上并不相同.(编辑更糟糕的是,这种想法是实现得很笨拙,给人实例的Monoid约束,当仅Semigroup是必要的.我想看到的Semigroup-extends-TO- Monoid想法实现,但不为Maybe.)
Kleisli特别是回过头来看,我们有三个明显的候选实例:
Monoid (Kleisli m a a)与returnKleisli组成MonadPlus m => Monoid (Kleisli m a b)提升mzero和mplus逐点->Monoid b => Monoid (Kleisli m a b)升降的幺半结构b上m然后->我希望没有做出任何选择,只是因为不清楚做出哪个选择.我犹豫不决,但我的投票将是2,优先考虑来自Kleisli m a结构的结构b.