为什么 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
实例能给您什么。我认为让您了解 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
.
的情况下采用左偏选项
现在为什么不能为 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
只是第二种类型变量的应用仿函数(a
在 Either e a
的情况下)。所以 Either e
的身份需要 e
也有一个身份。虽然可以构造一个类型,其中 e
有一个 Alternative
的实例,但是你不能为 Alternative
为 Either
和 e
创建一个实例,因为class 类型定义中没有这样的约束(类似于:(Alternative e, Applicative (f e)) => Alternative (f e)
)。
TL;DR:很抱歉我的乱七八糟失去了你,简而言之就是 f
在 Either
的情况下是错误的种类,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 如果你愿意的话;它是一个单一的更高种类的东西,但它与 Monoid
和 Semigroup
的关系没有定义,这显然(在文档中)明确地形成了一个层次结构。
我敢肯定在图书馆邮件列表上进行了大量讨论,如果有一些明显的 "correct" 解决方案,转向它们可能会导致(在最坏的情况下是无声的)损坏.
我是一个 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
实例能给您什么。我认为让您了解 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
.
现在为什么不能为 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
只是第二种类型变量的应用仿函数(a
在 Either e a
的情况下)。所以 Either e
的身份需要 e
也有一个身份。虽然可以构造一个类型,其中 e
有一个 Alternative
的实例,但是你不能为 Alternative
为 Either
和 e
创建一个实例,因为class 类型定义中没有这样的约束(类似于:(Alternative e, Applicative (f e)) => Alternative (f e)
)。
TL;DR:很抱歉我的乱七八糟失去了你,简而言之就是 f
在 Either
的情况下是错误的种类,Alternative
需要f :: * -> *
,而Either
是种类 Either :: * -> * -> *
所以 Maybe
可以有一个 Alternative
的实例,因为它有 种类 Maybe : * -> *
并且有一个身份概念(Nothing
) empty
所要求的。查看 Alternative
的所有实例并注意每个实例数据类型的种类。
你可以通过 :k
:
λ > :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 如果你愿意的话;它是一个单一的更高种类的东西,但它与 Monoid
和 Semigroup
的关系没有定义,这显然(在文档中)明确地形成了一个层次结构。
我敢肯定在图书馆邮件列表上进行了大量讨论,如果有一些明显的 "correct" 解决方案,转向它们可能会导致(在最坏的情况下是无声的)损坏.