我有一个类Foo
,它将类型构造函数F
作为类型参数:
case class Foo[F[_]](x: F[String])
现在我想定义一个成员方法bar
,它仅适用于某些固定的外部类型Outer
F[T] = Outer[Inner[T]]
,例如 Option
:
def bar[Inner[_]](implicit ev: ???): Foo[Inner]
???
必须是自然转换F ~> Outer·Inner
·
是类型构造函数的组合。
- 这个隐含的论点是什么样的?
- 我怎样才能从某个地方得到它?
如何编写类型构造函数组合?
还有如何最好地编写类型构造函数的组成?我目前使用lambda类型编写({type L[X] = Outer[Inner[X]]})#L
。
类型构造函数的类型相等性
我不认为 ScalaZ 中定义了它,但以 scalaz.Leibniz
为模板,制作一个相当简单。我不会专注于构图和便利方法,只得到实质内容:
sealed abstract class LeibnizK[F[_], G[_]] {
def subst[Z[_[_]]](p: Z[F]): Z[G]
}
object LeibnizK {
implicit def refl[F[_]] = new LeibnizK[F, F] {
override def subst[Z[_[_]]](p: Z[F]): Z[F] = p
}
}
这似乎是您正在寻找的隐式内容:
type Outer[A] = Option[A]
type Id[A] = A
case class Foo[F[_]](me: F[String]) {
// Oh boy, here comes type lambda
def bar[Inner[_]](implicit leibk: LeibnizK[
F,
({type L[A] = Outer[Inner[A]]})#L
]): Outer[Foo[Inner]] = leibk.subst(this).me.map(Foo(_)) // <- OK to use methods of Outer
}
assert(Foo[Option](Some("meh")).bar[Id] == Some(Foo[Id]("meh")))
- 斯卡拉小提琴
更好的类型组合语法
查看种类投影仪编译器插件。它允许您编写:
λ[A => Outer[Inner[A]]
// or
Lambda[A => Outer[Inner[A]]
而不是
({type L[A] = Outer[Inner[A]]})#L
对于简单情况(无嵌套),语法甚至更短
(?, Int)
而不是
({type L[A] = (A, Int)})#L