`F[_]: Sync` 中的 `F` 是什么?它来自哪里?

ger*_*s.b 3 generics scala typeclass higher-kinded-types scala-cats

我想使用该存储库中的 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]] =
Run Code Online (Sandbox Code Playgroud)

它是什么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)

    // ...
Run Code Online (Sandbox Code Playgroud)

Mar*_*lic 10

想一些具体的东西,比如“一盒巧克力”

case class Box(v: Chocolate)
Run Code Online (Sandbox Code Playgroud)

现在想象我们拿走巧克力,并让盒子容纳任何类型的元素A,也许是一盒硬币,一盒糖果,一盒卡片等

case class Box[A](v: A)
Run Code Online (Sandbox Code Playgroud)

这里我们在盒子的元素类型上是多态的。许多语言都可以表达这种级别的多态性。但 Scala 更进一步。就像我们拿走巧克力一样,我们也可以拿走盒子本身,本质上表达了“任何类型元素的任何上下文”的非常抽象的概念。

trait Ctx[F[_]]
Run Code Online (Sandbox Code Playgroud)

作为另一个类比,请考虑以下内容

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[_]]
Run Code Online (Sandbox Code Playgroud)

现在重点关注_ of _. 这里我们有“某种东西”,看起来好像我们什么都没有。我们能用这个做什么呢?这就是类型类的想法发挥作用的地方。类型类可以约束高度多态的形状,例如F[_]

def apply[F[_]: Sync](...)
Run Code Online (Sandbox Code Playgroud)

这里[F[_]: Sync]代表这个约束。这意味着该方法apply接受任何第一类类型构造函数,并且有证据表明它满足类型 class 的约束Sync。注意类型类Sync

trait Sync[F[_]]
Run Code Online (Sandbox Code Playgroud)

被认为是高阶类型构造函数,而类型参数F[_]表示一阶类型构造函数。相似地

F[_] : Sync : Concurrent
Run Code Online (Sandbox Code Playgroud)

指定类型构造函数F不仅必须满足Sync约束,还必须满足Concurrent类型class的约束等等。这些技术有时听起来很可怕

高阶类型构造函数多态性

但我相信大多数程序员已经具备了理解它的所有概念工具,因为

  1. 如果您曾经将函数传递给函数,那么您可以使用高阶概念
  2. 如果您曾经使用过 a List,那么您可以使用类型构造函数的概念
  3. 如果您曾经编写过对整数和双精度使用相同实现的方法,那么您可以使用多态性的概念

使用 Scala 的机制提供类型构造函数满足类型类约束的证据implicit。IMO Scala 3 显着简化了这个概念,因此请考虑https://dotty.epfl.ch/docs/reference/contextual/type-classes.html