我一直在玩scala cats,最后被隐式和类型限制所困。
假设以下定义:
trait Client[F[_]] {
def fetchPossiblePairs(fetcher: Uri => F[List[String]]): F[List[Rate.Pair]]
def fetchQuotes(currencyPairs: List[Rate.Pair], fetcher: Uri => F[List[QuoteDTO]]): F[List[Rate]]
def convertRate(uri: Uri): F[List[QuoteDTO]]
def symbols(uri: Uri): F[List[String]]
}
object Quotes {
private def getCurrencyPairs[F[_]: Monad](client: Client[F],
existingRates: Map[Rate.Pair, Rate]): F[List[Rate.Pair]] =
if (existingRates.isEmpty) {
client.fetchPossiblePairs(client.symbols)
} else {
existingRates.keySet.toList.pure[F]
}
private def updateCache(existingRates: Map[Rate.Pair, Rate], newRates: List[Rate]): Map[Rate.Pair, Rate] =
newRates.foldRight(existingRates)((rate: Rate, acc: Map[Rate.Pair, Rate]) => acc.updated(rate.pair, rate))
}
下面的实现可以工作,但看起来很丑,而且不符合标准:
object Quotes {
private def refreshRatesCache[F[_]: Monad](client: Client[F],
existingRates: Map[Rate.Pair, Rate]): F[Map[Rate.Pair, Rate]] = {
val currencyPairs1 = getCurrencyPairs(client, existingRates)
Monad[F]
.flatMap(currencyPairs1)(currencyPairs => client.fetchQuotes(currencyPairs, uri => client.convertRate(uri)))
.map(quotes => updateCache(existingRates, quotes))
}
}
使用for
理解,IDE会显示错误Cannot resolve symbol flatMap
:
object Quotes {
private def refreshRatesCache[F[_]: Monad](client: Client[F],
existingRates: Map[Rate.Pair, Rate]): F[Map[Rate.Pair, Rate]] =
for {
currencyPairs <- getCurrencyPairs(client, existingRates)
// ^
// |--- Cannot resolve symbol flatMap
//
rates <- client.fetchQuotes(currencyPairs, uri => client.convertRate(uri))
} yield updateCache(existingRates, rates)
}
SBT显示了一个稍微不同的错误:
value flatMap is not a member of type parameter F[List[Rate.Pair]]
我的理解是,这两个实现是相同的,只是使用了不同的语法糖。getCurrencyPairs[F[_]: Monad](...)
返回一个 Package 的List
、F[List[Rate.Pair]]
,并且给定F[_]: Monad
上的类型约束,我假设Scala应该能够推断出F extends Monad
并找到Monad
的所有方法(包括flatMap
)。
整个for
解析都在F[_]
的相同上下文中工作,因此似乎不是类型不匹配。
我试图扩展隐式和for
的理解,因此得到了这个丑陋的实现:
Monad[F]
.flatMap
(getCurrencyPairs(client, existingRates))
(currencyPairs => client.fetchQuotes(currencyPairs, uri => client.convertRate(uri)))
.map(quotes => updateCache(existingRates, quotes))
在我看来,使用(implicit m: Monad[F[_]])
没有太大意义(至少我无法给出它的正确用法)。
我对Scala隐式并不是很精通,但我的代码似乎有些问题。我哪里错了?
我使用的版本是:
- Scala
2.13.5
- SBT
1.9.0
- cats-core
2.5.0
- cats-effects
2.4.1
1条答案
按热度按时间n6lpvg4x1#
这几乎肯定是由于缺少提供方法的导入。
添加
import cats.syntax.all._