gpt4 book ai didi

scala - 在 Scala 中是否使用上下文绑定(bind)或隐式 ev

转载 作者:行者123 更新时间:2023-12-04 17:51:36 25 4
gpt4 key购买 nike

根据风格指南 - Scala 中的类型类应该使用什么经验法则 - context boundimplicit ev符号?

这两个例子做的一样

上下文绑定(bind)有更简洁的函数签名,但需要 val使用 implicitly 进行评估称呼:

def empty[T: Monoid, M[_] : Monad]: M[T] = {
val M = implicitly[Monad[M]]
val T = implicitly[Monoid[T]]
M.point(T.zero)
}
implicit ev方法自动将类型类插入到函数参数中,但会污染方法签名:
def empty[T, M[_]](implicit T: Monoid[T], M: Monad[M]): M[T] = {
M.point(T.zero)
}

我检查过的大多数库(例如 "com.typesafe.play" %% "play-json" % "2.6.2" )都使用 implicit ev
你在用什么,为什么?

最佳答案

这是非常基于意见的,但直接使用隐式参数列表的一个实际原因是您执行的隐式搜索更少。

当你这样做

def empty[T: Monoid, M[_] : Monad]: M[T] = {
val M = implicitly[Monad[M]]
val T = implicitly[Monoid[T]]
M.point(T.zero)
}

这被编译器脱糖成
def empty[T, M[_]](implicit ev1: Monoid[T], ev2: Monad[M]): M[T] = {
val M = implicitly[Monad[M]]
val T = implicitly[Monoid[T]]
M.point(T.zero)
}

所以现在 implicitly方法需要再进行一次隐式搜索才能找到 ev1ev2在适用范围。

这不太可能产生明显的运行时开销,但在某些情况下它可能会影响您的编译时性能。

相反,如果你这样做
def empty[T, M[_]](implicit T: Monoid[T], M: Monad[M]): M[T] =
M.point(T.zero)

您正在直接访问 MT从第一次隐式搜索开始。

另外(这是我个人的观点)我更喜欢 body 更短,以签名中的一些样板为代价。

我知道的大多数大量使用隐式参数的库在需要访问实例时都会使用这种样式,所以我想我只是对这种表示法更加熟悉了。

奖励,如果您决定使用上下文绑定(bind),通常最好提供 apply搜索隐式实例的类型类上的方法。这允许你写
def empty[T: Monoid, M[_]: Monad]: M[T] = {
Monad[M].point(Monoid[T].zero)
}

有关此技术的更多信息: https://blog.buildo.io/elegant-retrieval-of-type-class-instances-in-scala-32a524bbd0a7

关于scala - 在 Scala 中是否使用上下文绑定(bind)或隐式 ev,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45977978/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com