你希望一个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
一个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
)的应用函子。所以一个身份 forEither e
也需要e
有一个身份。虽然可以构造一个类型,其中e
有一个实例,Alternative
你不能为它创建一个实例Alternative
,Either
因为e
类型类定义中没有这样的约束(类似于:)(Alternative e, Applicative (f e)) => Alternative (f e)
。
TL;DR : 很抱歉,如果我在漫无边际f
的情况下失去了你,唯一的缺点是如果Either
是错误的类型,Alternative
需要f :: * -> *
whileEither
是类型的 Either :: * -> * -> *
所以Maybe
可以有一个 的实例,Alternative
因为它有种类 Maybe : * -> *
并且Nothing
有empty
. 查看所有实例Alternative
并注意每个实例数据类型的种类。
你可以在 ghci 中找到一种数据类型:k
:
λ > :k Maybe
Maybe :: * -> *
λ > :k Either
Either :: * -> * -> *