在Scala中为高级类型键入约束
我试图在
scala中为Functors编写一个通用法则,我可以在scalacheck测试中为许多仿函数重用这种格式.法律应该由构造函数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 } } 现在这个有效,但它并不理想.我需要为每个测试实例化我想要运行的类,并且需要在那里提供任意的ARM函数.当然,编译器需要这个函数,但对于许多类型,它们存在应该这样做的含义(例如对于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[_]] 现在是如何解决它. def functorLaw[A,F[_]] (fn :Functor[F])(implicit arb: Arbitrary[F[A]]) :Prop = forAll { (fa :F[A]) => true } 并且因为F [A]不出现在类型参数列表中(有A和F,而不是F [A]),所以不能使用“上下文绑定”语法糖,我们不得不使用显式(!)隐式参数列表. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |