如何用Kind-Projector正确声明批量处理的自然变换?
用Kind-Projector直接声明嵌套高阶类型的正确写法
你遇到的编译错误,核心原因是F[List[*]]的解析不符合预期:编译器把List[*]当成了* -> *的类型构造器,传给需要*类型参数的F[_],导致类型kind不匹配;同时Test trait要求参数是* -> *的类型构造器,但F[List[*]]最终是一个*类型,完全不符合要求。
正确的Kind-Projector写法
不需要额外类型别名,直接用Kind-Projector的λ表达式语法就能声明目标类型构造器:
import scala.language.higherKinds import scalaz.~> // 若使用Cats则替换为cats.~> trait Test[F[_]] { def foo: F[Int] } // 使用λ表达式构造*->*类型 def withBatching[F[_]](t: Test[F], nat: F ~> λ[A => F[List[A]]]): Test[λ[A => F[List[A]]]] = { new Test[λ[A => F[List[A]]]] { override def foo: F[List[Int]] = nat(t.foo) } }
更简洁的语法(Kind-Projector 0.11.0+)
如果你的Kind-Projector版本在0.11.0及以上,可以用更简洁的占位符语法,直接写成F[List[*]]替代λ表达式,插件会自动将其解析为对应的高阶类型构造器:
def withBatching[F[_]](t: Test[F], nat: F ~> F[List[*]]): Test[F[List[*]]] = { new Test[F[List[*]]] { override def foo: F[List[Int]] = nat(t.foo) } }
原写法报错的原因
原代码中F[List[*]]被编译器直接解析为F应用到List[*](即λ[α => List[α]]),但F[_]需要的是单个类型(kind为*),而非类型构造器(kind为* -> *),因此触发“takes no type parameters, expected: 1”的错误——因为F[List[*]]最终是一个*类型,无法作为Test的参数(Test需要* -> *类型)。
内容的提问来源于stack exchange,提问作者Some Name
相关产品推荐
相关产品推荐

