gpt4 book ai didi

scala - Scala中高级类型的类型约束

转载 作者:行者123 更新时间:2023-12-01 02:06:07 25 4
gpt4 key购买 nike

我正在尝试为 scala 中的 Functors 编写一个通用定律,其格式可以在 scalacheck 测试中用于许多 functors。该定律应该由构造函数 F[_] 和元素的类型参数化,比如 A。

理想情况下,我会写这样的东西:

def functorLaw[A, F[_] :Arbitrary] (fn :Functor[F]) :Prop = forAll { (fa :F[A]) => true }

(我使用 true 而不是法律主体,因为确切的计算对我的问题无关紧要)

然而,我能破解的最好方法是将它包装在一个抽象类中,提供一个抽象隐式来生成任意 F[A] 值:
abstract class  FunctorSpec[A :Arbitrary, F[_]] extends Properties("foo") {

implicit def arbitraryFA :Arbitrary[F[A]]
def functorLaw (fn :Functor[F]) :Prop = forAll { (fa :F[A]) => true }

}

现在这可行,但并不理想。我需要为每个要运行的测试实例化该类,并且需要在那里提供任意FA 函数。当然,编译器需要这个函数,但是对于很多类型来说,它们存在应该这样做的隐含(例如 List[Int])。但是编译器将无法猜测这些隐式提供了任意FA,所以我需要自己实现这个,这是非常重复的。例如:
object IntListFunctorSpec extends FunctorSpec[Int, List] {
def arbitraryFA :Arbitrary[List[Int]] = Arbitrary(arbitrary[List[Int]])

...
}

我认为我不需要告诉 scalacheck 如何构建 int 列表。有什么建议可以更优雅地做到这一点吗?

我尝试了其他关于高级类型边界的问题,但我无法弄清楚如何使用它们,即使它们听起来很接近。所以我想我会问。

最佳答案

你的尝试没有成功的原因是因为你有一种不匹配。
以下:

def functorLaw[A, F[_] :Arbitrary] (fn :Functor[F]) :Prop = forAll { (fa :F[A]) => true }

只是一个语法糖:
def functorLaw[A, F[_]] (fn :Functor[F])(implicit evidence: Arbitrary[F]) :Prop = forAll { (fa :F[A]) => true }

所以本质上,问题是你的方法需要一个隐式类型的值 Arbitrary[F]其中 F 是高阶类型( F[_] ),但这没有意义,因为 Arbitrary不采用高阶类型:
// T is a first order type, it has the kind *
// Simply put, it is not a type constructor
class Arbitrary[T]

为了让您的代码按原样编译(并且有意义), Arbitrary必须声明如下:
// T is a type constructor, it has the kind * -> *
class Arbitrary[T[_]]

现在来看看如何修复它。
在您的情况下,您想要的实际任意值的类型为 F[A] ,而不是 F (不用说,因为它不是具体类型,而是类型构造函数),所以你需要的隐式类型是 Arbitrary[F[A]] :
def functorLaw[A, F[_]] (fn :Functor[F])(implicit arb: Arbitrary[F[A]]) :Prop = forAll { (fa :F[A]) => true }

因为 F[A]不会出现在类型参数列表中(有 AF ,但没有 F[A] ),不能使用“上下文绑定(bind)”语法糖,我们必须使用显式(!)隐式参数列表。

关于scala - Scala中高级类型的类型约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32588756/

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