在Scala中推荐高级类型的限制是什么?
在以下简化示例代码中:
case class One[A](a: A) // An identity functor case class Twice[F[_],A](a: F[A],b: F[A]) // A functor transformer type Twice1[F[_]] = ({type L[α] = Twice[F,α]}) // We'll use Twice1[F]#L when we'd like to write Twice[F] trait Applicative[F[_]] // Members omitted val applicativeOne: Applicative[One] = null // Implementation omitted def applicativeTwice[F[_]](implicit inner: Applicative[F]): Applicative[({type L[α] = Twice[F,α]})#L] = null 我可以在applicativeOne上调用applicativeTwice,并且在我尝试在applicativeTwice(applicativeOne)上调用它时,键入推断工作,推理失败: val aOK = applicativeTwice(applicativeOne) val bOK = applicativeTwice[Twice1[One]#L](applicativeTwice(applicativeOne)) val cFAILS = applicativeTwice(applicativeTwice(applicativeOne)) scala 2.10.0中的错误是 - type mismatch; found : tools.Two.Applicative[[α]tools.Two.Twice[tools.Two.One,α]] required: tools.Two.Applicative[F] - no type parameters for method applicativeTwice: (implicit inner: tools.Two.Applicative[F])tools.Two.Applicative[[α]tools.Two.Twice[F,α]] exist so that it can be applied to arguments (tools.Two.Applicative[[α]tools.Two.Twice[tools.Two.One,α]]) --- because --- argument expression's type is not compatible with formal parameter type; found : tools.Two.Applicative[[α]tools.Two.Twice[tools.Two.One,α]] required: tools.Two.Applicative[?F] 为什么“?F”与任何(正确的类型)匹配? 解决方法
您遇到了一个常见的烦恼:
SI-2712.为了清楚起见,我将尽量减少代码:
import language.higherKinds object Test { case class Base[A](a: A) case class Recursive[F[_],A](fa: F[A]) def main(args: Array[String]): Unit = { val one = Base(1) val two = Recursive(one) val three = Recursive(two) // doesn't compile println(three) } } 这表明与您的类型错误相同: argument expression's type is not compatible with formal parameter type; found : Test.Recursive[Test.Base,Int] required: ?F val three = Recursive(two) // doesn't compile ^ 首先你可能已经知道了一些语法和术语: >在Scala中,我们说一个简单的,没有参数化的数据类型(如Int)有kind _。它是单形的 Scala一般不会有较高类型的麻烦。这是区分其类型系统(例如Java)的几个关键功能之一。但是,在处理较高类型的类型时,部分应用类型参数确实有问题。 这是问题:递归[F [_],A]有两个类型参数。在你的示例代码中,你做了“类型lambda”的技巧来部分应用第一个参数,如: val one = Base(1) val two = Recursive(one) val three = { type λ[α] = Recursive[Base,α] Recursive(two : λ[Int]) } 这使得编译器能够向递归构造函数提供一些正确的类型(_ [_])。如果Scala有咖喱类型参数列表,我一定会在这里使用: case class Base[A](a: A) case class Recursive[F[_]][A](fa: F[A]) // curried! def main(args: Array[String]): Unit = { val one = Base(1) // Base[Int] val two = Recursive(one) // Recursive[Base][Int] val three = Recursive(two) // Recursive[Recursive[Base]][Int] println(three) } 唉,没有(见SI-4719)。所以,据我所知,处理这个问题的最常见的方法是“不能使用的技巧”,因为Miles Sabin。这是在scalaz中出现的一个非常简化的版本: import language.higherKinds trait Unapply[FA] { type F[_] type A def apply(fa: FA): F[A] } object Unapply { implicit def unapply[F0[_[_],_],G0[_],A0] = new Unapply[F0[G0,A0]] { type F[α] = F0[G0,α] type A = A0 def apply(fa: F0[G0,A0]): F[A] = fa } } 在某些手写波浪的术语中,这个Unapply构造就像一个“一流的类型lambda”。我们定义一个表示一些类型FA可以分解为类型构造函数F [_]和类型A的断言的特征。然后在其伴随对象中,我们可以定义含义以提供各种类型的特定分解。我只在这里定义了我们需要使递归适合的具体的,但你可以写别人。 有了这个额外的管道,我们现在可以做我们需要的: import language.higherKinds object Test { case class Base[A](a: A) case class Recursive[F[_],A](fa: F[A]) object Recursive { def apply[FA](fa: FA)(implicit u: Unapply[FA]) = new Recursive(u(fa)) } def main(args: Array[String]): Unit = { val one = Base(1) val two = Recursive(one) val three = Recursive(two) println(three) } } 当当!现在输入推理工作,这个编译。作为一个练习,我建议你创建一个额外的课程: case class RecursiveFlipped[A,F[_]](fa: F[A]) …这与递归没有任何有意义的方式真的不同,当然,但会再次打破类型推论。然后定义修复它所需的附加管道。祝你好运! 编辑 你要求一个不太简化的版本,一些知道类型类的东西。需要进行一些修改,但希望您可以看到相似之处。首先,这是我们升级的Unapply: import language.higherKinds trait Unapply[TC[_[_]],FA] { type F[_] type A def TC: TC[F] def apply(fa: FA): F[A] } object Unapply { implicit def unapply[TC[_[_]],F0[_[_],A0](implicit TC0: TC[({ type λ[α] = F0[G0,α] })#λ]) = new Unapply[TC,F0[G0,A0]] { type F[α] = F0[G0,α] type A = A0 def TC = TC0 def apply(fa: F0[G0,A0]): F[A] = fa } } 再次,这是completely ripped off from scalaz.现在一些使用它的示例代码: import language.{ implicitConversions,higherKinds } object Test { // functor type class trait Functor[F[_]] { def map[A,B](fa: F[A])(f: A => B): F[B] } // functor extension methods object Functor { implicit class FunctorOps[F[_],A](fa: F[A])(implicit F: Functor[F]) { def map[B](f: A => B) = F.map(fa)(f) } implicit def unapply[FA](fa: FA)(implicit u: Unapply[Functor,FA]) = new FunctorOps(u(fa))(u.TC) } // identity functor case class Id[A](value: A) object Id { implicit val idFunctor = new Functor[Id] { def map[A,B](fa: Id[A])(f: A => B) = Id(f(fa.value)) } } // pair functor case class Pair[F[_],A](lhs: F[A],rhs: F[A]) object Pair { implicit def pairFunctor[F[_]](implicit F: Functor[F]) = new Functor[({ type λ[α] = Pair[F,α] })#λ] { def map[A,B](fa: Pair[F,A])(f: A => B) = Pair(F.map(fa.lhs)(f),F.map(fa.rhs)(f)) } } def main(args: Array[String]): Unit = { import Functor._ val one = Id(1) val two = Pair(one,one) map { _ + 1 } val three = Pair(two,two) map { _ + 1 } println(three) } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |