问题标签 [either]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
scala - Try[Result], IO[Result], Either[Error,Result],到底应该用哪个
我想知道我的方法的签名应该是什么,以便我优雅地处理不同类型的失败。
这个问题是我已经对 Scala 中的错误处理提出的许多问题的总结。你可以在这里找到一些问题:
目前,我了解以下内容:
- 两者都可以用作可能失败的方法调用的结果包装器
- Try 是偏右的 Either,失败是非致命的异常
- IO (scalaz) 有助于构建处理 IO 操作的纯方法
- 所有 3 个都可以在理解中轻松使用
- 由于不兼容的 flatMap 方法,所有 3 个都不容易在 for 理解中混合
- 在函数式语言中,我们通常不会抛出异常,除非它们是致命的
- 我们应该在非常特殊的情况下抛出异常。我想这是 Try 的方法
- 创建 Throwables 对 JVM 有性能成本,并且不打算用于业务流控制
存储层
现在请考虑我有一个UserRepository
. UserRepository
存储用户并定义findById
方法。可能会发生以下故障:
- 致命的失败(
OutOfMemoryError
) - IO 失败,因为数据库不可访问/不可读取
此外,用户可能会丢失,从而导致Option[User]
结果
使用存储库、SQL 的 JDBC 实现,可以抛出非致命异常(违反约束或其他),因此使用 Try 是有意义的。
当我们处理 IO 操作时,如果我们想要纯函数,那么 IO monad 也是有意义的。
所以结果类型可能是:
Try[Option[User]]
IO[Option[User]]
- 别的东西?
服务层
现在让我们介绍一个业务层,UserService
它提供了一些updateUserName(id,newUserName)
使用之前定义的方法findById
的存储库的方法。
可能会发生以下故障:
- 所有存储库故障都传播到服务层
- 业务错误:无法更新不存在的用户的用户名
- 业务错误:新用户名太短
那么结果类型可能是:
Try[Either[BusinessError,User]]
IO[Either[BusinessError,User]]
- 别的东西?
这里的 BusinessError 不是 Throwable,因为它不是异常失败。
使用理解
我想继续使用 for-comprehensions 来组合方法调用。
我们不能轻易地在理解上混合不同的 monad,所以我想我应该为我的所有操作使用某种统一的返回类型,对吧?
我只是想知道,在现实世界的 Scala 应用程序中,当可能发生不同类型的故障时,您如何成功地继续使用 for-comprehensions。
现在,为了理解对我来说效果很好,使用所有返回Either[Error,Result]
但所有不同类型的故障都融合在一起的服务和存储库,处理这些故障变得有点笨拙。
您是否定义了不同类型的 monad 之间的隐式转换以便能够用于理解?
您是否定义了自己的 monad 来处理故障?
顺便说一句,也许我很快就会使用异步 IO 驱动程序。所以我想我的返回类型可能更复杂:IO[Future[Either[BusinessError,User]]]
任何建议都会受到欢迎,因为我真的不知道该使用什么,而我的应用程序并不花哨:它只是一个 API,我应该能够区分可以显示给客户端的业务错误,以及技术错误。我试图找到一个优雅而纯粹的解决方案。
scala - 当使用 EitherT[StateWithSomeFixedStateType, T, U] 时,当返回 left 时如何进行一些状态操作?
假设您有一个看起来像这样的 EitherT:
如果您有一个可以返回左的理解:
你如何跟进一个在自身返回左侧之前操纵状态的理解?
我想我想要一些非常接近 orElse 的东西,但是 orElse 无法访问左侧的值:
如果它需要像 (x: => Int => EitherT[F, AA, BB]) 而不是仅仅 (x: => EitherT[F, AA, BB]),它会起作用。
我曾尝试从:
但是如果我从调用 isLeft 开始,看起来计算至少运行了两次,一次是为 isLeft,一次是在我调用 leftMap 之类的东西时。
在这里使用什么是正确的?
haskell - 是否可以在单子序列中更改单子类型?
我知道可以更改包装类型,以便您可以拥有
但有可能改变m
吗?如果m
is a MonadError
and 由 an Either ErrorA
and实现Either ErrorB
,我可以以某种方式链接它们吗?显然我不能直接将它们链接起来,因为 的类型是Left
什么?但是,无论哪种情况,我最终都会打电话show
,但我没有找到比这更好的解决方案
它无法正确使用在第一个错误处停止的单子行为,而无需我进行明确检查。
scala - Scala.Either orElse 方法
Either
在 Scala 中使用 's 的惯用方式是什么?例如,当使用Option
I时orElse
,如果 current 为 ,则可以使用方法获取下一个可选值None
。但是如何以Either
同样的方式工作呢?我没有找到像orElse
链接 Either's 的方法(而且我知道拥有这种方法并不是一个好主意,因为我们失去了Left
价值)
编辑:事实上,我有一个if-elseif-elseif-else
表达式序列,每个都返回Right
or Left
。我想重构我的代码,让它变得“更实用”。firstOption orElse secondOption orElse...
所以我可以用if来替换它Option
,但是如何在这里使用Either
呢?
scala - Scala.Either getOrElse 方法
为什么当我输入这一切都很好?
但是当我输入这个编译失败?
编译错误:
value getOrElse 不是 java.io.Serializable
println(RightString, Int.left getOrElse RightString, Int.left getOrElse LeftString, Int)的成员
所以我不能链接getOrElse
方法调用
scala - Scala 中的链式验证
我有一个case class
包含命令行配置信息的 Scala:
我正在编写一个验证函数来检查每个值是否为Some
:
但是如果我理解 Haskell 的 monad,似乎我应该能够将验证链接在一起(伪语法):
如果任何config.XXX
表达式返回Failure
,整个事情 ( validateConfig
) 应该失败,否则Success(config)
应该返回。
有没有办法用Try
或者其他类来做到这一点?
scala - 在 Scala 中结合 Futures (Twitter) 和 Either
我们使用 Twitter 期货(作为 Finagle 堆栈的一部分),我不喜欢使用(业务)异常来控制应用程序流的概念,因为异常不会出现在方法签名中。
所以我有了用 Future[Either[A,B]] 作为替代的想法。
但是我在使用这个概念对期货进行理解时遇到了一些问题:
例如,我们有一个存储库方法:
和一个处理程序方法,它使用这个 repo 并执行一些其他检查并创建一个令牌
getUserCredentialsByNickname(..) 之后的 for comprehension 中的调用仅应在此调用返回 Right[UserCredentials] 时执行,而且每个返回的 Either 的详细错误信息也应从处理程序返回。
scala - 用于 if 守卫的理解
如何使用 if guard 进行推导?
我在使用它时遇到了这个错误。
编辑: 我遇到了另一个错误。我认为如果使用防护,它会返回一个选项结果。
编辑2
scala - 对于 if guard throws error 的理解
当我以这种方式使用 if guard 进行理解时出现一个错误。
代码:
错误: