如何通过隐式分解类型构造函数



我有一个类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 ·是类型构造函数的组合。

  1. 这个隐含的论点是什么样的?
  2. 我怎样才能从某个地方得到它?

如何编写类型构造函数组合?

还有如何最好地编写类型构造函数的组成?我目前使用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

最新更新