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

时间:2017-06-10 10:01:07

标签: haskell either semigroup

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

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

此实例丢弃或更正“错误”,当两个操作数都标记为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)

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

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

2 个答案:

答案 0 :(得分:8)

您希望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的情况下采用左偏置选项。

现在为什么你没有Alternative的{​​{1}}个实例。如果您查看属于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, (<|>) #-} 的概念;这是empty运算符的标识。案件中的身份意味着身份和其他东西之间的替代方案始终是其他东西。

现在,您将如何构建(<|>)的身份?如果查看Either e a实例上的约束,您可以看到Alternative实例需要f。没问题,ApplicativeEither声明了Applicative个实例。正如您所看到的,Either e只是第二个类型变量(Either上的a)的应用函子。因此,Either e a的身份需要Either e才能拥有身份。虽然可以构建e具有e实例的类型,但您无法为Alternative Alternative生成Either的实例e因为类型类定义中没有这样的约束(类似于(Alternative e, Applicative (f e)) => Alternative (f e))。

TL; DR :如果我在漫无边际的情况下失去了你,我很抱歉,f Either的情况是错误的< em> kind ,Alternative需要f :: * -> *Either属于种类 Either :: * -> * -> *

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

您可以使用:k找到ghci中的数据类型:

λ > :k Maybe
Maybe :: * -> *
λ > :k Either
Either :: * -> * -> *

答案 1 :(得分:1)

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

instance Alternative (Either a) where ...

你需要能够凭空捏造一些价值Either a b&#34;&#34;那是你的身份对象。一个可能的实例可能是:

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

你也问为什么Semigroup实例的定义方式是这样的,坦白说我也不理解它。您建议的实例似乎也允许(兼容/合法)Monoid实例:

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

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

所以情况并不好。问题的一部分是Alternative如果你愿意,那就是一个二等课程;它是一个幺半形的更高级的东西,但它与MonoidSemigroup的关系,显然和明确地(在文档中)形成一个层次结构,没有被定义。

我确定在图书馆邮件列表上进行了大量讨论,如果有一些明显的&#34;正确的&#34;解决方案很可能转移到它们可能会导致(在最坏的情况下是无声的)破损。