我们可以用Alternative做什么,但不能用Monoid做什么?

ais*_*ais 9 monads haskell monoids

我读了为什么MonadPlus而不是Monad + Monoid?我理解理论上的差异,但我无法弄清楚实际的差异,因为对于List来说它看起来是一样的.

mappend [1] [2] == [1] <|> [2]
Run Code Online (Sandbox Code Playgroud)

是.也许有不同的实现

mappend (Just "a") (Just "b") /= (Just "a") <|> (Just "b")
Run Code Online (Sandbox Code Playgroud)

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

instance Monoid (Maybe a) where
  Nothing `mappend` m = m
  m `mappend` _ = m
Run Code Online (Sandbox Code Playgroud)

那么,有人可以展示代码示例,它解释了Alternative和Monoid之间的实际区别吗?

问题不是为什么MonadPlus而不是Monad + Monoid?

Dan*_*ner 15

这是一个可以做的事情的一个非常简单的例子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)
Run Code Online (Sandbox Code Playgroud)

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

flattenMonoid :: (Foldable f, Applicative f) => Nested f a -> f a
flattenMonoid (Leaf x) = pure x
flattenMonoid (Branch b) = fold (flattenMonoid b)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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)
Run Code Online (Sandbox Code Playgroud)

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

如果我们能写的话会很酷

flattenMonoid :: ((forall a. Monoid a => Monoid (f a)), Foldable f, Applicative f, Monoid (f a)) => Nested f a -> f a
Run Code Online (Sandbox Code Playgroud)

甚至只是

flattenMonoid :: ((forall a. Monoid (f a)), Foldable f, Applicative f) => Nested f a -> f a
Run Code Online (Sandbox Code Playgroud)

我们可以:而不是写作forall a. Monoid (f a),我们写Alternative f.(我们可以编写一个表达第一个,更容易满足约束的类型类.)