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

标签 haskell monads monoids alternative-functor monadplus

我读了Why MonadPlus and not Monad + Monoid?我理解理论上的区别,但我无法弄清楚实际的区别,因为对于 List 它看起来是一样的。

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

是的。也许有不同的实现
mappend (Just "a") (Just "b") /= (Just "a") <|> (Just "b")

但是我们可以像 Alternative 一样实现 Maybe Monoid
instance Monoid (Maybe a) where
  Nothing `mappend` m = m
  m `mappend` _ = m

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

该问题与 Why MonadPlus and not Monad + Monoid? 不重复

最佳答案

这是一个非常简单的例子,可以用 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)

现在让我们用 Monoid 尝试同样的事情。 :
flattenMonoid :: (Foldable f, Applicative f) => Nested f a -> f a
flattenMonoid (Leaf x) = pure x
flattenMonoid (Branch b) = fold (flattenMonoid b)

当然,这不会编译,因为在 fold (flattenMonoid b)我们需要知道扁平化会产生一个容器,其中的元素是 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)

啊,但是现在我们有一个问题,因为我们不能满足递归调用的上下文,它需要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)

好吧,这只会让问题变得更糟,因为现在递归调用需要更多的东西,即 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

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

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

关于haskell - 我们可以用 Alternative 做什么,但不能用 Monoid 做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31770710/

相关文章:

haskell - 如何展平haskell中的列表列表

haskell - .cabal 文件语法的完整定义

haskell - Haskell 中的递归 IO

新类型的 Haskell Monoid 实例问题

c++ - std::min/float monoid 的标识元素

haskell - 具体的例子表明单子(monad)在组合下不是封闭的(有证明)?

haskell - 非维护者上传到 Hackage

javascript - 如何编写TaskT Monad Transformer来组合异步计算和其他效果?

haskell - 将 StateT 与 InputT 结合

haskell - 对于类型对齐的序列,我如何用 foldMap 来表达 foldr?