我们可以用Alternative做什么,但不能用Monoid做什么? [英] What can we do with Alternative but cannot do with Monoid?

查看:142
本文介绍了我们可以用Alternative做什么,但不能用Monoid做什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读了为什么选择MonadPlus而不是Monad + Monoid?并且我明白理论上的差异,但我无法找出实际的区别,因为对于List,它看起来是一样的。

  mappend [1] [ 2] == [1]< |> [2] 

是的。也许有不同的实现

  mappend(只是a)(只是b)/ =(只是a)< ; |> (只是b)

但是我们可以像Alternative一样实现Maybe Monoid

  instance Monoid(也许a)其中
没有`mappend` m = m
m`mappend` _ = m $因此,有人可以展示解释Alternative和Monoid之间实际区别的代码示例吗?



这个问题不是重复的为什么选择MonadPlus而不是Monad + Monoid?

解决方案

这是一个非常简单的例子,与替代

  import Control.Applicative 
import Data .Foldable

数据嵌套fa = Leaf a |分支(嵌套f(f a))

flatten ::(可折叠f,可选f)=>嵌套f a - > fa
flatten(Leaf x)= pure x
flatten(Branch b)= asum(flatten b)

现在让我们用 Monoid 来尝试同样的事情:

  flattenMonoid ::(Foldable f,Applicative f)=>嵌套f a  - > fa 
flattenMonoid(Leaf x)=纯x
flattenMonoid(Branch b)= fold(flattenMonoid b)

当然,这不会编译,因为在 fold(flattenMonoid b)中,我们需要知道flattening会生成一个容器,其元素是一个 Monoid 的实例。因此,让我们将其添加到上下文中:

pre $ flatnewMonoid ::(可折叠f,应用f,Monoid(f a))=>嵌套f a - > fa
flattenMonoid(Leaf x)=纯x
flattenMonoid(Branch b)= fold(flattenMonoid b)

啊,但现在我们遇到了一个问题,因为我们无法满足递归调用的上下文,这需要 Monoid(f(fa))。所以让我们将其添加到上下文中:

$ $ $ $ $ $ $ $ $ $ $ $ $> flattenMonoid ::(Foldable f,Applicative f,Monoid(fa),Monoid(f (fa)))=>嵌套f a - > fa
flattenMonoid(Leaf x)=纯x
flattenMonoid(Branch b)= fold(flattenMonoid b)

好吧,这只会让问题变得更糟,因为现在递归调用需要更多的东西,即 Monoid(f(f(fa))) ...



如果我们可以写出

  flattenMonoid ::((forall a。Monoid a => Monoid(fa)),Foldable f,Applicative f,Monoid(fa))=>嵌套f a  - > fa 

甚至只是

  flattenMonoid ::((forall a。Monoid(fa)),Foldable f,Applicative f)=>嵌套f a  - > f a 

我们可以:而不是写 forall a。 Monoid(f a),我们写 Alternative f 。 (我们可以编写一个类型类来表示第一个容易被满足的约束)。

I read Why MonadPlus and not Monad + Monoid? and I understand a theoretical difference, but I cannot figure out a practical difference, because for List it looks the same.

mappend [1] [2] == [1] <|> [2]

Yes. Maybe has different implementations

mappend (Just "a") (Just "b") /= (Just "a") <|> (Just "b")

But we can implement Maybe Monoid in the same way as Alternative

instance Monoid (Maybe a) where
  Nothing `mappend` m = m
  m `mappend` _ = m

So, can someone show the code example which explains a practical difference between Alternative and Monoid?

The question is not a duplicate of Why MonadPlus and not Monad + Monoid?

解决方案

Here is a very simple example of something one can do with Alternative:

import Control.Applicative
import Data.Foldable

data Nested f a = Leaf a | Branch (Nested f (f a))

flatten :: (Foldable f, Alternative f) => Nested f a -> f a
flatten (Leaf x) = pure x
flatten (Branch b) = asum (flatten b)

Now let's try the same thing with Monoid:

flattenMonoid :: (Foldable f, Applicative f) => Nested f a -> f a
flattenMonoid (Leaf x) = pure x
flattenMonoid (Branch b) = fold (flattenMonoid b)

Of course, this doesn't compile, because in fold (flattenMonoid b) we need to know that the flattening produces a container with elements that are an instance of Monoid. So let's add that to the context:

flattenMonoid :: (Foldable f, Applicative f, Monoid (f a)) => Nested f a -> f a
flattenMonoid (Leaf x) = pure x
flattenMonoid (Branch b) = fold (flattenMonoid b)

Ah, but now we have a problem, because we can't satisfy the context of the recursive call, which demands Monoid (f (f a)). So let's add that to the context:

flattenMonoid :: (Foldable f, Applicative f, Monoid (f a), Monoid (f (f a))) => Nested f a -> f a
flattenMonoid (Leaf x) = pure x
flattenMonoid (Branch b) = fold (flattenMonoid b)

Well, that just makes the problem worse, since now the recursive call demands even more stuff, namely Monoid (f (f (f a)))...

It would be cool if we could write

flattenMonoid :: ((forall a. Monoid a => Monoid (f a)), Foldable f, Applicative f, Monoid (f a)) => Nested f a -> f a

or even just

flattenMonoid :: ((forall a. Monoid (f a)), Foldable f, Applicative f) => Nested f a -> f a

and we can: instead of writing forall a. Monoid (f a), we write Alternative f. (We can write a typeclass that expresses the first, easier-to-satisfy constraint, as well.)

这篇关于我们可以用Alternative做什么,但不能用Monoid做什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆