Scala 类型约束和广义类型约束的区别
The difference between Scala type bound and generalized type constraints
两个方法在特征 Foo 上的约束是否有足够的差异?
trait Foo[A] {
def barWithTypeBound[B <: A]: B
def barWithGeneralizedTypeConstraint[B](implicit ev: B <:< A): B
}
有时在调用点生成证据比通过所有中间层提供证据更容易,例如
trait Flattenable[F[_]] {
def flatten[A](ffa: F[F[A]]): F[A]
}
extension [F[_], A](fa: F[A])
def flatten[B](using A <:< F[B], F: Flattenable[F]): F[B] =
F.flatten(fa)
要在没有 <:<
的情况下实现此扩展,我将不得不更改 fa:
的定义
extension [F[_], A](fa: F[F[A]])
def flatten[B](using F: Flattenable[F]): F[B] =
F.flatten(fa)
这在这里是可能的,但并非在所有情况下。另一个例子是这样的:
class Wrapper[A](value: A):
def get: A = value
def isNatural(using: A <:< Int): Boolean = value >= 0
def isTrue(using A <:< Boolean): Boolean = value
只允许调用者调用A
特定类型的方法。 (但同样,您可以使用专门的扩展方法和法线约束来解决这些问题)。我能够在一个地方定义参数类型,并在稍后对其施加额外的约束。如果我从一开始就需要这种约束,我会使用类型绑定。
通常,不需要根据类型使某些方法(或隐式,或给定)可用或不可用。而且它只能证明某些特定情况是真实的,因此它不能很好地处理协和矛盾。而且,它要求您创建一个虚拟对象。因此,除了少数情况外,这种“hack”很有用,一般的约束是首选。
在您的示例中,这两种方法之间没有区别,除了第二种方法必须传递额外的对象作为参数。
两个方法在特征 Foo 上的约束是否有足够的差异?
trait Foo[A] {
def barWithTypeBound[B <: A]: B
def barWithGeneralizedTypeConstraint[B](implicit ev: B <:< A): B
}
有时在调用点生成证据比通过所有中间层提供证据更容易,例如
trait Flattenable[F[_]] {
def flatten[A](ffa: F[F[A]]): F[A]
}
extension [F[_], A](fa: F[A])
def flatten[B](using A <:< F[B], F: Flattenable[F]): F[B] =
F.flatten(fa)
要在没有 <:<
的情况下实现此扩展,我将不得不更改 fa:
extension [F[_], A](fa: F[F[A]])
def flatten[B](using F: Flattenable[F]): F[B] =
F.flatten(fa)
这在这里是可能的,但并非在所有情况下。另一个例子是这样的:
class Wrapper[A](value: A):
def get: A = value
def isNatural(using: A <:< Int): Boolean = value >= 0
def isTrue(using A <:< Boolean): Boolean = value
只允许调用者调用A
特定类型的方法。 (但同样,您可以使用专门的扩展方法和法线约束来解决这些问题)。我能够在一个地方定义参数类型,并在稍后对其施加额外的约束。如果我从一开始就需要这种约束,我会使用类型绑定。
通常,不需要根据类型使某些方法(或隐式,或给定)可用或不可用。而且它只能证明某些特定情况是真实的,因此它不能很好地处理协和矛盾。而且,它要求您创建一个虚拟对象。因此,除了少数情况外,这种“hack”很有用,一般的约束是首选。
在您的示例中,这两种方法之间没有区别,除了第二种方法必须传递额外的对象作为参数。