我是一个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
或所涉及的类型类。
答案 0 :(得分:8)
您希望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
好吧,主要区别似乎是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
。没问题,Applicative
为Either
声明了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
如果你愿意,那就是一个二等课程;它是一个幺半形的更高级的东西,但它与Monoid
和Semigroup
的关系,显然和明确地(在文档中)形成一个层次结构,没有被定义。
我确定在图书馆邮件列表上进行了大量讨论,如果有一些明显的&#34;正确的&#34;解决方案很可能转移到它们可能会导致(在最坏的情况下是无声的)破损。