scala - Where to use `ApplicativeError` instead of `Either`?
问题描述
There is ApplicativeError[F,E]
+ F[A]
and there is Either[E, A]
. Both convey the message that the function could fail with an E
or succeed with an A
but I'm not sure about the different message they convey to the client about the intended way of handling the error :
def f1[F[_]: Applicative[F]]: F[Either[E, A]]
def f2[F[_]: ApplicativeError[F,E]]: F[A]
I understand f1
means: client is responsible for error handling. But what does f2
mean to the client about how to handle the error ?
解决方案
ApplicativeError[F, E]
假设 of 的类型以E
某种方式被编码,F
并且您可以创建实例 of ApplicativeError[F, E]
only 因为对于这个特定F
的情况,有 error 是有意义的E
。例子:
ApplicativeError[Task, Throwable]
-Task
用作错误通道,因此暴露为错误代数Throwable
是有意义的。Throwable
事实上Sync[F]
,Cats Effect implementsMonadError[F, Throwable]
反过来实现ApplicativeError[F, Throwable]
了 Cats Effect 的许多类型类假设您只处理Throwable
ApplicativeError[Task[Either[E, *]], E]
- 在这样的组合中,您将E
同时拥有 typeF
的特定定义和E
参数 - 这对于所有类型的双函子都是典型的:Task[Either[E, *]]
,EitherT[Task, E, *]
, ZIO'sIO[E, A]
等等
该接口ApplicativeError[F, E]
不自行处理错误。但它公开了方法:
raiseError[A](e: E): F[A]
- 这会产生错误handleErrorWith[A](fa: F[A])(f: (E) ⇒ F[A]): F[A]
- 处理它
这样你就可以告诉它如何处理它。
两者都可以在不假设错误的性质和 F 其他Applicative
可能失败的情况下工作。如果您只使用F
和键入类,则可以使用这些方法从错误中恢复。如果您知道F
呼叫站点的确切类型(因为它被硬编码为Task
、IO
、Coeval
等),您可以直接使用恢复方法。
主要区别在于结果F[Either[E, A]]
不会告诉调用者E
应该被视为失败。F[A]
告诉我们只有A
成功的价值。此外,一个需要Applicative
while 另一个ApplicativeError
,因此创建值所需的“功率”有所不同 - 如果您看到ApplicativeError
即使没有E
结果,您也可以假设该方法可能会失败,因为它需要更强大的类型类。
但当然它不是一成不变的,它主要是关于表达意图,因为无论你在哪里,你都F[A]
可以转换为F[Either[E, A]]
使用ApplicativeError[F, E]
(甚至还有像attempt[A](fa: F[A]): F[Either[E, A]]
or之类的方法fromEither[A](x: Either[E, A]): F[A]
)。因此,在您的应用程序的一部分中,您可以F[A]
使用E
代数,但是您可以使用一个纯函数来使用Either[E, A] => B
它——然后您可以转换、映射,并在必要时转换回来。
TL; DR 它主要是关于表达意图,因为两者在“道德上”是平等的。
推荐阅读
- python-3.x - 我该怎么办?(类型错误)
- c++ - c++中的简单计算器奇怪的结果
- python - 带有日期参数的函数在数据帧上运行
- python - 将 Chrome 标志与 QtWebEngine (PyQt5) 一起使用
- node.js - API 未根据 lambda 授权方的响应调用 lambda 并返回 null 消息
- python - 在烧瓶中获取 HTML 输入并返回数据
- c# - 在数组初始化中指定特定值
- android - Android:Toast 在函数执行后显示,期望它在之前显示
- vb.net - VB.Net: Access Base class variable from derived class
- c++ - 动画问题 - 翻译、投影 OpenGL/C++