4

从类的名称和解析器中的用法来看,Maybe我认为它的行为是从a <|> b <|> c. 所以我希望输入

[] <|> [1] <|> [2, 3]

它将返回第一个非空列表,即:

[1]

但它实际上只是连接了整个事情,产生:

[1,2,3]

所以我想知道这种实现背后的原因是什么?它真的正确吗?

http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Applicative.html#t:Alternative

PS是否有任何标准功能可以满足我的期望Alternative

4

4 回答 4

4

原因(嗯,一个原因)是它与MonadPlus实例匹配。

据我所知,当一个类型同时具有 和 的实例时,这些实例匹配是可取的MonadPlusAlternative因为AlternativetoApplicative的关系类似于 to 的MonadPlus关系Monad

对于你想要的行为,如果你想使用Alternative,你需要一个newtype列表的包装器,作为一个独立的函数,它当然也很容易定义。

[] <++ xs = xs
xs <++ _  = xs
于 2013-01-07T12:48:57.967 回答
4

这是预期的行为。该类Alternative为应用函子定义了一个幺半群(因此(Applicative f) =>定义中的类约束)。

AlternativeApplicativeMonadPlushas to具有相同的关系MonadAlternative列表的实例给出与列表的实例相同的行为MonadPlus(也与列表的实例相同的行为) ,这是有道理的Monoid

不过,这不是列表幺半群的唯一有效定义。你的定义:

instance Monoid [a] where
  mempty = []
  [] `mappend` xs = xs
  xs `mappend` _  = xs

也满足幺半群定律(练习:检查这个!)所以你可以定义一个新类型

newtype Lst a = Lst { getLst :: [a] }

并将其制成Monoid/ Alternative/etc 实例,或者只是定义自己的函数来做你想做的事,如 Daniel Fischer 的回答。

于 2013-01-07T12:50:29.827 回答
3

Alternative 只是为应用函子定义的一个幺半群。因此,如果满足幺半群定律,则应用函子的 Alternative 实例是正确的。

我不知道是否有标准功能可以做到这一点,但您当然可以实现自己的功能或定义自己的替代实例。

您可以在typeclassopedia中阅读更多关于它们的信息。它详细解释了所有这些类型类以及它们要遵循的规律。

于 2013-01-07T12:46:19.513 回答
3

在实现Alternative f(或MonadPlus f)实例时,您必须选择一个幺半群并使用andf a来实现它。对于某些结构,例如列表,可能存在多种可能性。列表最自然的幺半群操作是它们的连接(作为标识元素)。正如您所建议的,采用第一个非空元素也是一种可能性,但对于列表来说并不自然。您的操作几乎忽略了列表的结构(长度),它只检查列表是否为空。而且它没有添加任何新内容,因为这种幺半群运算已经可以作为的 的实例使用,它旨在表示(非)空值。empty<|>[]MaybeAlternative

这也体现在 of 的实例MonadPlus[]。正如HaskellWiki上所述,对于以下情况,有两组可能的法律MonadPlus

  • Monoid + LeftZero + LeftDistribution - 由[]
  • Monoid + LeftZero + LeftCatch - 由和Maybe统计。IOSTM

如果我们选择你的Alternativeand实现MonadPlus,那么我们只有满足的实例... + LeftCatch,没有满足 LeftDistribution 的实例。再一次,MonadPlusof与of[]没有太大区别。而且我们不会有任何东西可以让我们解决诸如send+more=money之类的问题。所以选择/ of来连接会更有趣。MonadPlusMaybemplus<|>[]

于 2013-01-07T20:27:08.893 回答