16

我是 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对所涉及的类型类有错误的概念。

4

2 回答 2

16

你希望一个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一个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有一个Applicative实例。没关系,Either有一个ApplicativeEither e. 如您所见,Either它只是第二个类型变量(a在 的情况下Either e a)的应用函子。所以一个身份 forEither e也需要e有一个身份。虽然可以构造一个类型,其中e有一个实例,Alternative你不能为它创建一个实例AlternativeEither因为e类型类定义中没有这样的约束(类似于:)(Alternative e, Applicative (f e)) => Alternative (f e)

TL;DR : 很抱歉,如果我在漫无边际f的情况下失去了你,唯一的缺点是如果Either是错误的类型Alternative需要f :: * -> *whileEither类型的 Either :: * -> * -> *

所以Maybe可以有一个 的实例,Alternative因为它有种类 Maybe : * -> *并且Nothingempty. 查看所有实例Alternative并注意每个实例数据类型的种类。

你可以在 ghci 中找到一种数据类型:k

λ > :k Maybe
Maybe :: * -> *
λ > :k Either
Either :: * -> * -> *
于 2017-06-10T10:49:05.487 回答
4

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

instance Alternative (Either a) where ...

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

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属于二等舱。它是一个单面的更高种类的东西,但它与Monoidand的关系Semigroup,显然和明确地(在文档中)形成了一个层次结构,没有定义。

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

于 2017-06-10T17:52:14.560 回答