为什么没有替代实例,但是半群的行为类似于替代?

10 haskell either semigroup

我是一个Haskell新手,我想知道为什么没有替代实例,Either但是半群,其行为与我期望的替代:

instance Semigroup (Either a b) where
Left _ <> b = b
a      <> _ = a
Run Code Online (Sandbox Code Playgroud)

此实例丢弃或更正"错误",当两个操作数都被标记时Right,它将采用第一个.这不是替代品提供的"选择"吗?

我希望semigroup实例看起来大致如下:

instance (Semigroup b) => Semigroup (Either a b) where
Left e  <> _       = Left e
_       <> Left e  = Left e
Right x <> Right y = Right (x <> y)
Run Code Online (Sandbox Code Playgroud)

这意味着它传播错误并附加常规结果.

我想我有一个错误的概念Either或涉及的类型类.

bas*_*nry 11

您希望Alternative实例给您什么?我认为让你了解方法Alternative和方法的一个好方法Semigroup是查看另一个具有两个实例的类型:例如Maybe String:

? > Just "a" <> Just "b"
Just "ab"
? > Just "a" <> Nothing
Just "a"
? > Nothing <> Just "b"
Just "b"
? > Nothing <> Nothing
Nothing


? > Just "a" <|> Just "b"
Just "a"
? > Just "a" <|> Nothing
Just "a"
? > Nothing <|> Just "b"
Just "b"
? > Nothing <|> Nothing
Nothing
Run Code Online (Sandbox Code Playgroud)

好吧,所以主要的区别似乎是Just "a"Just "b".这是有道理的,因为在结合它们的情况下,Semigroup而不是在情况下采用左偏置选项Alternative.

现在为什么你不能有一个Alternative实例Either.如果查看属于Alternative类类的函数:

? > :i Alternative
class Applicative f => Alternative (f :: * -> *) where
  empty :: f a
  (<|>) :: f a -> f a -> f a
  some :: f a -> f [a]
  many :: f a -> f [a]
  {-# MINIMAL empty, (<|>) #-}
Run Code Online (Sandbox Code Playgroud)

看起来它定义了一个概念empty; 这是(<|>)运营商的身份.案件中的身份意味着身份和其他东西之间的替代方案始终是其他东西.

现在,你将如何构建一个身份Either e a?如果查看Alternative实例上的约束,可以看到它需要f有一个Applicative实例.没关系,Either有一个Applicative实例申报Either e.正如你所看到的,Either它只是第二个类型变量的应用函子(a在这种情况下Either e a).因此,对于一个身份Either e需要e也有一个身份.虽然有可能构建一个类型,其中e有一个实例Alternative,你不能让一个实例AlternativeEithere因为没有这样的限制是在类型类定义(东西线沿线的:(Alternative e, Applicative (f e)) => Alternative (f e)).

TL; DR:对不起,如果我失去了你和我的散漫,短期的它是f在的情况下Either是错误的那种,Alternative需要f :: * -> *同时Either一种 Either :: * -> * -> *

所以Maybe可以有一个实例,Alternative因为它有种类, Maybe : * -> *并且有一个Nothing所需的identity()概念empty.查看所有实例Alternative并注意每种实例数据类型的种类.

您可以在ghci中找到数据类型:k:

? > :k Maybe
Maybe :: * -> *
? > :k Either
Either :: * -> * -> *
Run Code Online (Sandbox Code Playgroud)

  • 抱歉,仍然存在一个问题:正如预期的那样,`Just "a" &lt;&gt; Just "b" == Just "ab"`,但是 `Right "a" &lt;&gt; Right "b" == Right "a"`。为什么会有这样的差异? (2认同)

jbe*_*man 6

根据上面 Dietrich Epp 发布的票证,问题Alternativeempty。如果你有:

instance Alternative (Either a) where ...
Run Code Online (Sandbox Code Playgroud)

您需要能够Either a b“凭空”提取一些作为您的身份对象的值。一种可能的情况可能是:

instance (Monoid a)=> Alternative (Either a) where 
  empty = Left mempty
  ...
Run Code Online (Sandbox Code Playgroud)

您还问为什么Semigroup实例是这样定义的,坦白说我也不明白。看来您建议的实例也将允许(兼容/合法)Monoid实例:

instance Monoid b=> Monoid (Either a b) where
  mempty = Right mempty
Run Code Online (Sandbox Code Playgroud)

这将与实例一致Maybe(Maybe 和 Either 之间的代数关系是显而易见的)。

所以情况不太好。部分问题是,Alternative如果你愿意的话,这有点像二等舱;它是一个幺半群的更高种类的东西,但它与Monoid和 的关系Semigroup,显然并明确地(在文档中)形成了一个层次结构,尚未定义。

我确信图书馆邮件列表上已经进行了大量讨论,如果有一些明显的“正确”解决方案,那么转向它们可能会导致(在最坏的情况下无声的)破坏。