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

Haskell 我们可以用Alternative做什么,但不能用Monoid做什么?,haskell,monads,monoids,alternative-functor,monadplus,Haskell,Monads,Monoids,Alternative Functor,Monadplus,我阅读并理解了理论上的差异,但我无法找出实际的差异,因为列表看起来是一样的 mappend [1] [2] == [1] <|> [2] 那么,有人能给出一个代码示例来解释替代和幺半群之间的实际区别吗 这个问题不是重复的这里有一个非常简单的例子,可以用替代方法来做: import Control.Applicative import Data.Foldable data Nested f a = Leaf a | Branch (Nested f (f a)) flatten

我阅读并理解了理论上的差异,但我无法找出实际的差异,因为列表看起来是一样的

mappend [1] [2] == [1] <|> [2]
那么,有人能给出一个代码示例来解释替代和幺半群之间的实际区别吗


这个问题不是重复的

这里有一个非常简单的例子,可以用
替代方法来做:

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)
现在让我们用
幺半群试试同样的方法:

flattenMonoid :: (Foldable f, Applicative f) => Nested f a -> f a
flattenMonoid (Leaf x) = pure x
flattenMonoid (Branch b) = fold (flattenMonoid b)
当然,这不会编译,因为在
fold(flattlemonoidb)
中,我们需要知道展平生成了一个容器,其中的元素是
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)
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(fa))
。让我们把它添加到上下文中:

flattenMonoid :: (Foldable f, Applicative f, Monoid (f a)) => Nested f a -> f a
flattenMonoid (Leaf x) = pure x
flattenMonoid (Branch b) = fold (flattenMonoid b)
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(fa))

如果我们能写,那就太酷了

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

我们可以:而不是为所有a编写
。幺半群(fa)
,我们写
替代f
。(我们可以编写一个typeclass来表达第一个更容易满足约束的类型。)。。。对不起,这仍然是一个副本。弓形虫是你不能用
Monoid
做的,特别是第3点。和4.:“3.如果我们想使用无限多不同的
a
MonadPlus m=>…
而不是不可能的。4.如果我们不知道我们需要什么
a
MonadPlus m=>…
而不是不可能的。”如果你对此不清楚,请具体询问你的疑问。这只是理论上的解释。即使在那里,第一个评论也是“我真的希望看到一个具体的例子”。我想要一些实际的代码示例,这些示例可以显示3和4是如何影响幺半群的使用的。好的,我明白你的意思了。顺便提一下,我不认为编造一些人为的例子是有帮助的——当然,对于我们可以在这里给出的小例子,你总是可以说“现在我们为什么不抽象地公开那个私有数据类型”或者“那是几个
Monoid(fa),Monoid(fb)
约束,但那又怎样呢?——看起来没那么糟糕”或者“我不知道”“为什么我们不把那些无限多/未知的类型放在一个存在/GADT包装器中?”。但所有这些解决方法在大型项目中都不太实用。只需使用
Alternative
上下文查找一些库函数,并尝试使用
Monoid
编写它们。您是否删除了已关闭的问题并再次发布了它?请避免,这确实令人困惑。@ais请不要因为问题是c而删除它失败。相反,要么团结起来让它重新开放,要么问一个新问题(就像你在这里做的那样)并引用它,准确地解释新问题的不同之处。我认为你对这个问题的不同之处给出了很好的解释。但隐藏问题的历史有点卑鄙,可能会让人们产生误解。