scala - 斯卡拉,猫。有人可以解释什么是“F”,它来自哪里?
问题描述
我想使用该存储库中的猫传奇: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 _
. 在这里,我们有“某物”,这似乎我们什么都没有。我们该怎么做呢?这就是类型类的想法发挥作用的地方。类型类可以约束高度多态的形状,例如F[_]
def apply[F[_]: Sync](...)
这里[F[_]: Sync]
表示这个约束。这意味着该方法apply
接受任何有证据表明它满足类型类约束的第一类构造函数Sync
。注意类型类Sync
trait Sync[F[_]]
被认为是高阶类型构造函数,而类型参数F[_]
表示一阶类型构造函数。相似地
F[_] : Sync : Concurrent
指定类型构造函数F
不仅要满足Sync
约束,还要满足Concurrent
类型类的约束等等。这些技术有时被称为可怕的声音
高阶类型构造函数多态性
但是我相信大多数程序员已经拥有所有已经存在的概念工具来理解它,因为
- 如果您曾经将函数传递给函数,那么您可以使用高阶概念
- 如果您曾经使用过 a
List
,那么您可以使用类型构造函数的概念 - 如果您曾经编写过一个对整数和双精度数使用相同实现的方法,那么您可以使用多态性的概念
使用 Scala 的机制提供类型构造函数满足类型类约束的证据。implicit
IMO Scala 3 大大简化了这个概念,因此请考虑https://dotty.epfl.ch/docs/reference/contextual/type-classes.html
推荐阅读
- math - 为什么阶乘数的末尾有太多的零位
- reactjs - 热重载不适用于 react 和 webpack
- vis.js - 绘制 vis.js 网络时保持两个节点彼此相邻
- android - 多次调用 FirebaseApp.initializeApp 的缺点?
- javascript - 如何在此 chart.js 代码示例中销毁/更新图表数据?
- sql - 数据库属性
- javascript - 从nodejs发布/解析画布图像数据
- go - 在 golang 中批量处理来自 ms azure eventthub 的事件
- r - 如何在R中的现有数据框中添加新变量
- spring - 使用 spring security 和 mongodb 进行 Rest 身份验证