为什么 Either 没有替代实例,而是一个行为类似于替代的半群?

Why is there no alternative instance for Either but a semigroup that behaves similarily to alternative?

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

instance Semigroup (Either a b) where
Left _ <> b = b
a      <> _ = a

此实例丢弃或更正 "errors",当两个操作数都标记为 Right 时,它采用第一个。这不正是替代方案提供的 "choice" 吗?

我希望半群实例大致如下:

instance (Semigroup b) => Semigroup (Either a b) where
Left e  <> _       = Left e
_       <> Left e  = Left e
Right x <> Right y = Right (x <> y)

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

我想我对 Either 或相关类型 类 的理解有误。

您希望 Alternative 实例能给您什么。我认为让您了解 AlternativeSemigroup 有何不同的一个好方法是查看另一种具有两者实例的类型:例如 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

好的,所以主要区别似乎是 Just "a"Just "b"。这是有道理的,因为您在 Semigroup 的情况下将它们组合在一起,而不是在 Alternative.

的情况下采用左偏选项

现在为什么不能为 Either 创建一个 Alternative 实例。如果您查看属于 Alternative 类型 class:

的函数
λ > :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, (<|>) #-}

好像定义了一个empty的概念;这是 (<|>) 运算符的标识。案例中的身份意味着身份与其他事物之间的选择始终是其他事物。

现在,您将如何为 Either e a 构建身份?如果查看 Alternative 实例上的约束,您会发现它需要 f 才能拥有 Applicative 实例。没关系,Either 有一个为 Either e 声明的 Applicative 实例。如您所见,Either 只是第二种类型变量的应用仿函数(aEither e a 的情况下)。所以 Either e 的身份需要 e 也有一个身份。虽然可以构造一个类型,其中 e 有一个 Alternative 的实例,但是你不能为 AlternativeEithere 创建一个实例,因为class 类型定义中没有这样的约束(类似于:(Alternative e, Applicative (f e)) => Alternative (f e))。

TL;DR:很抱歉我的乱七八糟失去了你,简而言之就是 fEither 的情况下是错误的种类Alternative需要f :: * -> *,而Either种类 Either :: * -> * -> *

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

你可以通过 :k:

在 ghci 中找到数据类型的种类
λ > :k Maybe
Maybe :: * -> *
λ > :k Either
Either :: * -> * -> *

根据上面发布的 ticket Dietrich Epp,Alternative 的问题是 empty。如果你有:

instance Alternative (Either a) where ...

您需要能够提取一些值 Either a b "out of thin air",这是您的身份对象。一种可能的情况是:

instance (Monoid a)=> Alternative (Either a) where 
  empty = Left mempty
  ...

你还问为什么Semigroup实例是这样定义的,说实话我也不明白。您建议的实例似乎也允许 (compatible/lawful) Monoid 实例:

instance Monoid b=> Monoid (Either a b) where
  mempty = Right mempty

这将与 Maybe 实例一致(Maybe 和 Either 之间的代数关系很明显)。

所以情况不妙。部分问题是 Alternative 有点像秒 - class class 如果你愿意的话;它是一个单一的更高种类的东西,但它与 MonoidSemigroup 的关系没有定义,这显然(在文档中)明确地形成了一个层次结构。

我敢肯定在图书馆邮件列表上进行了大量讨论,如果有一些明显的 "correct" 解决方案,转向它们可能会导致(在最坏的情况下是无声的)损坏.