Either类似乎很有用,使用它的方法非常明显.但后来我看了API文档,我很困惑:
def joinLeft [A1 >: A, B1 >: B, C] (implicit ev: <:<[A1, Either[C, B1]]):
Either[C, B1]
Joins an Either through Left.
def joinRight [A1 >: A, B1 >: B, C] (implicit ev: <:<[B1, Either[A1, C]]):
Either[A1, C]
Joins an Either through Right.
def left : LeftProjection[A, B]
Projects this Either as a Left.
def right : RightProjection[A, B]
Projects this Either as a Right.
Run Code Online (Sandbox Code Playgroud)
我如何处理投影,如何调用连接?
Google只是向我指出了API文档.
这可能只是"不关注幕后人"的情况,但我不这么认为.我认为这很重要.
Did*_*ont 50
left并且right是重要的.Either在没有投影的情况下很有用(大多数情况下你会进行模式匹配),但投影非常值得关注,因为它们提供了更丰富的API.您将更少使用连接.
Either通常用来表示"适当的价值或错误".在这方面,它就像一个扩展Option.如果没有数据,则表示None您有错误.
Option有一个丰富的API.同样可以提供上Either,只要我们知道,无论是哪种,哪一个是结果,哪一个是错误.
left而right投影就是这样说的.它是Either,加上增加的知识,该值分别在左侧或右侧,另一个是错误.
例如,Option你可以映射,所以opt.map(f)返回Option与f应用,它的值opt,如果它有一个,仍然None如果opt是None.在左侧投影中,f如果它是a Left,它将应用于左侧的值,如果是a ,则将其保持不变Right.观察签名:
LeftProjection[A,B],map[C](f: A => C): Either[C,B]RightProjection[A,B],map[C](f: B => C): Either[A,C].left并且right只是当你想要使用一个通常的API例程时,说出哪一方被认为是值的方法.
替代方案可能是:
map例如更改错误),请执行swap之前和之后的操作.for内涵(flatMap事实上,但对于符号是相当方便的)Either是(检查)异常的替代品.现在加入.左和右意味着与投影相同,它们与投影密切相关flatMap.考虑joinLeft.签名可能令人费解:
joinLeft [A1 >: A, B1 >: B, C] (implicit ev: <:<[A1, Either[C, B1]]):
Either[C, B1]
Run Code Online (Sandbox Code Playgroud)
A1并且B1在技术上是必要的,但对理解并不重要,让我们简化
joinLeft[C](implicit ev: <:<[A, Either[C, B])
Run Code Online (Sandbox Code Playgroud)
什么隐含的意思是,如果该方法只能被称为A是一个Either[C,B].该方法一般不可用Either[A,B],但仅适用于Either[Either[C,B], B].与左投影一样,我们认为值在左边(适合joinRight).连接的作用是扁平化(想想flatMap).当一个连接时,不关心错误(B)是在内部还是外部,我们只想要[C,B].所以左(左(c))产生左(c),左(右(b))和右(b)产生右(b).与flatMap的关系如下:
joinLeft(e) = e.left.flatMap(identity)
e.left.flatMap(f) = e.left.map(f).joinLeft
Run Code Online (Sandbox Code Playgroud)
在Option相当于将努力上Option[Option[A]], Some(Some(x))将产生Some(x)两个Some(None)和None将产生None.它可以写成o.flatMap(身份).注意,它Option[A]是同形的Either[A,Unit](如果你使用左投影和连接),也是Either[Unit, A](使用右投影).
Kev*_*ght 20
暂时忽略连接,投影是一种允许您使用an Either作为monad的机制.可以把它想象成将左侧或右侧抽成一个Option,但不会丢失另一侧
与往常一样,这可能通过一个例子更有意义.所以想象你有一个Either[Exception, Int]并希望将其转换Exception为a String(如果存在)
val result = opReturningEither
val better = result.left map {_.getMessage}
Run Code Online (Sandbox Code Playgroud)
这将映射到结果的左侧,给你一个 Either[String,Int]
Ben*_*mes 14
joinLeft并joinRight让你"变平"的嵌套Either:
scala> val e: Either[Either[String, Int], Int] = Left(Left("foo"))
e: Either[Either[String,Int],Int] = Left(Left(foo))
scala> e.joinLeft
res2: Either[String,Int] = Left(foo)
Run Code Online (Sandbox Code Playgroud)
编辑:我对这个问题的回答显示了如何使用投影的一个例子,在这种情况下,将一系列Eithers 折叠在一起,没有模式匹配或调用isLeft或isRight.如果你熟悉如何在Option没有匹配或调用的情况下使用isDefined它,那就是类似的.
虽然好奇地看着Either的当前来源,但我看到了joinLeft并且joinRight通过模式匹配来实现.但是,我偶然发现了这个旧版本的源代码,并发现它用于使用投影实现连接方法:
def joinLeft[A, B](es: Either[Either[A, B], B]) =
es.left.flatMap(x => x)
Run Code Online (Sandbox Code Playgroud)