我想使用该存储库中的 cats-saga:https://github.com/VladKopanev/cats-saga
OrderSagaCoordinator.scala L160
处的那段代码上:
def apply[F[_]: Sync: Concurrent: Timer: Sleep: Parallel](
paymentServiceClient: PaymentServiceClient[F],
loyaltyPointsServiceClient: LoyaltyPointsServiceClient[F],
orderServiceClient: OrderServiceClient[F],
sagaLogDao: SagaLogDao[F],
maxRequestTimeout: Int
): F[OrderSagaCoordinatorImpl[F]] =
F
是什么,它从哪里来,有人可以解释一下那段代码吗?
谢谢
编辑:我知道什么是泛型类型。然而,在这种情况下,调用
apply
方法时不会指定具体类型,而且我看不到它来自的任何地方。
(for {
paymentService <- PaymentServiceClientStub(randomUtil, clientMaxReqTimeout, flakyClient)
loyaltyPoints <- LoyaltyPointsServiceClientStub(randomUtil, clientMaxReqTimeout, flakyClient)
orderService <- OrderServiceClientStub(randomUtil, clientMaxReqTimeout, flakyClient)
xa = Transactor.fromDriverManager[IO]("org.postgresql.Driver", "jdbc:postgresql:Saga", "postgres", "root")
logDao = new SagaLogDaoImpl(xa)
orderSEC <- OrderSagaCoordinatorImpl(paymentService, loyaltyPoints, orderService, logDao, sagaMaxReqTimeout)
// ...
想一些具体的东西,比如“一盒巧克力”
case class Box(v: Chocolate)
现在想象我们拿走巧克力,并让盒子容纳任何类型的元素
A
,也许是一盒硬币,一盒糖果,一盒卡片等
case class Box[A](v: A)
这里我们盒子的元素类型是多态的。许多语言都可以表达这种级别的多态性。但 Scala 更进一步。就像我们拿走巧克力一样,我们也可以拿走盒子本身,本质上表达了“任何类型元素的任何上下文”的非常抽象的想法
trait Ctx[F[_]]
作为另一个类比,请考虑以下内容
box of chocolate -> proper type -> case class Box(v: Chocolate)
box of _ -> type constructor of first order -> case class Box[A](v: A)
_ of _ -> type constructor of higher order -> trait Ctx[F[_]]
现在关注
_ of _
。这里我们有“某种东西”,看起来好像我们什么都没有。我们能用这个做什么呢?这就是 type class 的想法发挥作用的地方。类型类可以约束高度多态的形状,例如 F[_]
def apply[F[_]: Sync](...)
这里
[F[_]: Sync]
代表这个约束。这意味着方法 apply
接受任何第一类类型构造函数,并且有证据表明它满足类型类 Sync
的约束。请注意,键入 class Sync
trait Sync[F[_]]
被认为是高阶类型构造函数,而类型参数
F[_]
表示一阶类型构造函数。同样
F[_] : Sync : Concurrent
指定类型构造函数
F
不仅必须满足Sync
约束,还必须满足Concurrent
类型类的约束,等等。这些技术有时听起来很可怕
高阶类型构造函数多态性
但我相信大多数程序员已经拥有所有已经存在的概念工具来理解它,因为
List
,那么您可以使用类型构造函数implicit
机制提供类型构造函数满足类型类约束的证据
。 IMO Scala 3 显着简化了这个概念,因此请考虑https://dotty.epfl.ch/docs/reference/contextual/type-classes.html