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

How to decompose a type constructor via implicits?

我有一个 class Foo 将类型构造函数 F 作为类型参数:

case class Foo[F[_]](x: F[String])

现在我想定义一个成员方法 bar 只适用于 F[T] = Outer[Inner[T]] 某些固定的外部类型 Outer,例如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")))

更好的类型组合语法

查看 kind projector 编译器插件。它允许你写:

λ[A => Outer[Inner[A]]
// or
Lambda[A => Outer[Inner[A]]

而不是

({type L[A] = Outer[Inner[A]]})#L

对于简单的情况(无嵌套),还有更短的语法

(?, Int)

而不是

({type L[A] = (A, Int)})#L