如何在 Dotty 中使用 given?
How to use given in Dotty?
我正在查看 Contextual Abstractions
页面下的 Dotty
文档,我看到了 Given Instances
。
Given instances (or, simply, "givens") define "canonical" values of
certain types that serve for synthesizing arguments to given clauses.
Example:
trait Ord[T] {
def compare(x: T, y: T): Int
def (x: T) < (y: T) = compare(x, y) < 0
def (x: T) > (y: T) = compare(x, y) > 0
}
given intOrd: Ord[Int] {
def compare(x: Int, y: Int) =
if (x < y) -1 else if (x > y) +1 else 0
}
given listOrd[T]: (ord: Ord[T]) => Ord[List[T]] {
def compare(xs: List[T], ys: List[T]): Int = (xs, ys) match {
case (Nil, Nil) => 0
case (Nil, _) => -1
case (_, Nil) => +1
case (x :: xs1, y :: ys1) =>
val fst = ord.compare(x, y)
if (fst != 0) fst else compare(xs1, ys1)
}
}
但是 docs 中的这个示例从未解释如何使用 given
。我拉取了测试 Dotty
示例项目并尝试使用它,但我不太了解它。
是新关键字吗?我们进口它吗?还是我遗漏了什么。
下面是使用 given
实例的示例。假设我们要比较两个整数,看看哪个比另一个大。我们可以利用上面已经定义的 intOrd
并编写:
def whichIsBigger[T](x: T, y: T)(given ord: Ord[T]): String = {
ord.compare(x, y) match {
case -1 => s"$x is less than $y"
case 0 => s"$x and $y are equal"
case 1 => s"$x is greater than $y"
}
}
println(whichIsBigger(2, 1))
产生:
2 is greater than 1
我们能够做到这一点是因为范围内有一个命名的给定实例,否则编译器会抱怨它没有 Ord[Int]
.
Is it a new keyword ? Do we import it ? Or am I missing something.
这是一个新关键字,它替换了 Scala 2 中 implicit
定义的特定部分。如果这是 Scala 2,我们会写成:
implicit val intOrd: Ord[Int] = new Ord[Int] {
def compare(x: Int, y: Int) =
if (x < y) -1 else if (x > y) 1 else 0
}
def whichIsBigger[T](x: T, y: T)(implicit ord: Ord[T]): String
是的,这是一个新关键字,您可以从页面末尾的语法中使用 'given'
看出(第 "Syntax" 节)。它旨在取代 implicit
。如果你已经熟悉隐式,我认为 Relationship with Scala 2 Implicits 是很好的开始。
也许比较我们如何在 Scala 2 中使用 implicit
关键字和在 Scala 3 中使用 given
关键字定义类型类会很有启发:
trait Semigroup[A] {
def combine(x: A, y: A): A
}
object Semigroup {
def combine[A: Semigroup](x: A, y: A) = implicitly[Semigroup[A]].combine(x,y)
implicit val intSemigroup: Semigroup[Int] = new Semigroup[Int] {
def combine(x: Int, y: Int) = x + y
}
implicit val quxSemigroup: Semigroup[Qux] = new Semigroup[Qux] {
def combine(x: Qux, y: Qux) = Qux(x.a + y.a)
}
}
case class Qux(a: Int)
Semigroup.combine(41, 1)
Semigroup.combine(Qux(41), Qux(1))
trait Semigroup[A] {
def combine(x: A, y: A): A
}
object Semigroup {
def combine[A](x: A, y: A)(given Semigroup[A]) = summon.combine(x,y)
given intSemigroup: Semigroup[Int] {
def combine(x: Int, y: Int) = x + y
}
given quxSemigroup: Semigroup[Qux] {
def combine(x: Qux, y: Qux) = Qux(x.a + y.a)
}
}
case class Qux(a: Int)
Semigroup.combine(41, 1))
Semigroup.combine(Qux(41), Qux(1))
我正在查看 Contextual Abstractions
页面下的 Dotty
文档,我看到了 Given Instances
。
Given instances (or, simply, "givens") define "canonical" values of certain types that serve for synthesizing arguments to given clauses. Example:
trait Ord[T] {
def compare(x: T, y: T): Int
def (x: T) < (y: T) = compare(x, y) < 0
def (x: T) > (y: T) = compare(x, y) > 0
}
given intOrd: Ord[Int] {
def compare(x: Int, y: Int) =
if (x < y) -1 else if (x > y) +1 else 0
}
given listOrd[T]: (ord: Ord[T]) => Ord[List[T]] {
def compare(xs: List[T], ys: List[T]): Int = (xs, ys) match {
case (Nil, Nil) => 0
case (Nil, _) => -1
case (_, Nil) => +1
case (x :: xs1, y :: ys1) =>
val fst = ord.compare(x, y)
if (fst != 0) fst else compare(xs1, ys1)
}
}
但是 docs 中的这个示例从未解释如何使用 given
。我拉取了测试 Dotty
示例项目并尝试使用它,但我不太了解它。
是新关键字吗?我们进口它吗?还是我遗漏了什么。
下面是使用 given
实例的示例。假设我们要比较两个整数,看看哪个比另一个大。我们可以利用上面已经定义的 intOrd
并编写:
def whichIsBigger[T](x: T, y: T)(given ord: Ord[T]): String = {
ord.compare(x, y) match {
case -1 => s"$x is less than $y"
case 0 => s"$x and $y are equal"
case 1 => s"$x is greater than $y"
}
}
println(whichIsBigger(2, 1))
产生:
2 is greater than 1
我们能够做到这一点是因为范围内有一个命名的给定实例,否则编译器会抱怨它没有 Ord[Int]
.
Is it a new keyword ? Do we import it ? Or am I missing something.
这是一个新关键字,它替换了 Scala 2 中 implicit
定义的特定部分。如果这是 Scala 2,我们会写成:
implicit val intOrd: Ord[Int] = new Ord[Int] {
def compare(x: Int, y: Int) =
if (x < y) -1 else if (x > y) 1 else 0
}
def whichIsBigger[T](x: T, y: T)(implicit ord: Ord[T]): String
是的,这是一个新关键字,您可以从页面末尾的语法中使用 'given'
看出(第 "Syntax" 节)。它旨在取代 implicit
。如果你已经熟悉隐式,我认为 Relationship with Scala 2 Implicits 是很好的开始。
也许比较我们如何在 Scala 2 中使用 implicit
关键字和在 Scala 3 中使用 given
关键字定义类型类会很有启发:
trait Semigroup[A] {
def combine(x: A, y: A): A
}
object Semigroup {
def combine[A: Semigroup](x: A, y: A) = implicitly[Semigroup[A]].combine(x,y)
implicit val intSemigroup: Semigroup[Int] = new Semigroup[Int] {
def combine(x: Int, y: Int) = x + y
}
implicit val quxSemigroup: Semigroup[Qux] = new Semigroup[Qux] {
def combine(x: Qux, y: Qux) = Qux(x.a + y.a)
}
}
case class Qux(a: Int)
Semigroup.combine(41, 1)
Semigroup.combine(Qux(41), Qux(1))
trait Semigroup[A] {
def combine(x: A, y: A): A
}
object Semigroup {
def combine[A](x: A, y: A)(given Semigroup[A]) = summon.combine(x,y)
given intSemigroup: Semigroup[Int] {
def combine(x: Int, y: Int) = x + y
}
given quxSemigroup: Semigroup[Qux] {
def combine(x: Qux, y: Qux) = Qux(x.a + y.a)
}
}
case class Qux(a: Int)
Semigroup.combine(41, 1))
Semigroup.combine(Qux(41), Qux(1))