简体   繁体   中英

How to decompose a type constructor via implicits?

I have a class Foo that takes a type constructor F as type parameter:

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

Now I want to define a member method bar that is only applicable, if F[T] = Outer[Inner[T]] for some fixed outer type Outer , eg Option :

def bar[Inner[_]](implicit ev: ???): Foo[Inner]

The ??? must be something along a natural transformation F ~> Outer·Inner with · being composition of type constructors.

  1. How does this implicit argument look like?
  2. How can I get it from somewhere?

How to write type constructor composition?

Also how to best write composition of type constructors? I currently write using a type lambda ({type L[X] = Outer[Inner[X]]})#L .

Type equality for type constructors

I don't think there's one defined in ScalaZ, but it's fairly simple to make one, taking scalaz.Leibniz as a template. I won't focus on composition and convenience methods, and only get the substance:

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
  }
}

Which seems to be the implicit you're looking for:

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")))

Better syntax for type composition

Check out kind projector compiler plugin. It allows you to write:

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

instead of

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

And for simple cases (no nesting), there's even shorter syntax

(?, Int)

instead of

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM