如何通过隐式分解类型构造函数?
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
的东西,·
是类型构造函数的组合。
- 这个隐含的论点是什么样子的?
- 我怎样才能从某个地方得到它?
如何编写类型构造函数组合?
还有如何最好地编写类型构造函数的组合?我目前使用 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
我有一个 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
的东西,·
是类型构造函数的组合。
- 这个隐含的论点是什么样子的?
- 我怎样才能从某个地方得到它?
如何编写类型构造函数组合?
还有如何最好地编写类型构造函数的组合?我目前使用 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