Seb*_*ber 15 scala either scalaz
我想知道我的方法应该是什么签名,以便我优雅地处理不同类型的失败.
这个问题在某种程度上是我已经在Scala中处理错误的许多问题的总结.你可以在这里找到一些问题:
现在,我理解以下内容:
存储库层
现在请考虑我有一个UserRepository.所述UserRepository存储的用户,并限定了findById方法.可能发生以下故障:
OutOfMemoryError)此外,用户可能会丢失,从而导致Option[User]结果
使用存储库的JDBC实现,可以抛出SQL,非致命异常(约束违规或其他),因此使用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
我想继续使用for-comprehensions来组合方法调用.
我们不能轻易地将不同的monad混合起来进行理解,所以我想我的所有操作都应该有一些统一的返回类型吗?
我只是想知道你在现实世界的Scala应用程序中如何成功地在不同类型的故障发生时继续使用for-understanding.
对于现在来说,for-comprehension对我来说很好,使用服务和存储库都可以返回,Either[Error,Result]但是所有不同类型的故障都会融合在一起,并且处理这些故障会变得很糟糕.
您是否定义了不同类型的monad之间的隐式转换,以便能够使用for -reherehension?
你定义自己的monad来处理失败吗?
顺便说一下,我很快就会使用异步IO驱动程序.所以我想我的返回类型可能更复杂:IO[Future[Either[BusinessError,User]]]
任何建议都会受到欢迎,因为我真的不知道该使用什么,而我的应用程序并不花哨:它只是一个API,我应该能够区分可以向客户端显示的业务错误,以及技术错误.我试图找到一个优雅而纯粹的解决方案.
Pth*_*ame 15
这就是Scalaz的EitherTmonad变换器的用途.堆栈IO[Either[E, A]]等价EitherT[IO, E, A],除了前者必须按顺序处理为多个monad,而后者自动为单个monad,Either为基本monad 添加功能IO.您还可以使用EitherT[Future, E, A]向异步操作添加非异常错误处理.
Monad变换器通常是在单一for理解和/或单一操作中混合多个monad的需要的答案.
编辑:
我假设您使用的是Scalaz 7.0.0版.
为了在EitherTmonad上使用monad变换器IO,首先需要导入Scalaz的相关部分:
import scalaz._, scalaz.effect._
Run Code Online (Sandbox Code Playgroud)
您还需要定义你的错误类型: RepositoryError,BusinessError,等这照常工作.你只需要确保你可以,例如,将any转换RepositoryError为a BusinessError然后模式匹配,以恢复确切的错误类型.
然后你的方法的签名变成:
def findById(id: ID): EitherT[IO, RepositoryError, User]
def updateUserName(id: ID, newUserName: String): EitherT[IO, BusinessError, User]
Run Code Online (Sandbox Code Playgroud)
在每个方法中,您可以使用基于EitherT- 和 - IO的monad堆栈作为单个统一的monad,for像往常一样可用于in -rehe态. EitherT将负责IO通过整个计算线程化基本monad(在这种情况下),同时还按照Either通常的方式处理错误(默认情况下已经正确偏置,因此您不必经常处理所有常见的.right垃圾) .当您想要执行IO操作时,您所要做的就是使用liftIO实例方法将其提升到组合的monad堆栈中IO.
作为旁注,当以这种方式工作时,EitherT伴随对象中的函数可能非常有用.
@ pthariens-flame的回答很好,您应该将其用于手头的任务。
我想带上该领域最新发展的一些背景资料,所以这只是一个一般性的信息答案。
错误管理基本上是我们开发人员的第一工作。幸福的道路既快乐又无聊,这不是用户会抱怨的地方。大多数(全部?)问题都存在于过程中暗示效果(尤其是I / O)的地方。
解决这些问题的方法之一是遵循通常称为“纯FP方法”的方法,在此方法中,您在程序的纯/全部和不纯/非全部部分之间划了一条大的红线。这样做时,您可以利用可能性根据错误的类型来彻底处理错误。
在最近的时间(18个月?)中,Scala 在该领域进行了许多研究和开发。实际上,我相信Scala是当今所有语言中最棘手和最棘手的问题(但当然,这可能只是可用性/最新信息的大脑偏见)。
Scalaz8,Monix和cats-effects是这种快速发展的3个主要贡献者。因此,与这3个项目相关的任何内容(会议讨论,博客文章等)都将帮助您了解正在发生的事情。
因此,为了简短起见,Scalaz8将更改IO的建模方式,以更好地说明错误管理。John DeGoes领导着这项工作,他就该主题提供了一些很好的资源:
文章:
视频:
Monix和Cats-effect 也有很多事情要做,但是我相信,关于该主题的大多数资源都发生在相应项目中的请求请求中。
亚历山德鲁·内德尔库(Alexandru Nedelcu)的讲话为这些问题提供了一些背景知识:
亚当·沃斯基(Adam Warski)的比较:
最后,Luka Jacobowitz为Cats撰写的精彩文章:“重新思考MonadError” https://typelevel.org/blog/2018/04/13/rethinking-monaderror.html涵盖了很多相同的方面,其他的光。
[编辑]:正如同龄人所注意到的,域中(r)演化的跨度不止于斯卡拉地区。为了使效果编码(除其他外,IO)更具性能,需要做大量工作。域中的最新步骤正在尝试使用Kleisli Arrows代替monad,以最大程度地减少JVM上的GC流失。
看到:
希望能帮助到你!
更新:关于reddit的话题有很长很有趣的话题:“有人可以向我解释IO的好处吗?” https://www.reddit.com/r/scala/comments/8ygjcq/can_someone_explain_to_me_the_benefits_of_io/
约翰·德高斯(John DeGoes)的贡献:“斯卡拉战争:FP-OOP与FP” http://degoes.net/articles/fpoop-vs-fp
| 归档时间: |
|
| 查看次数: |
2519 次 |
| 最近记录: |