Add meaningful toString to TypeFunctions

It can be hard to debug these because the toString output for a kind
projector plugin provided lambda is inscrutable.
This commit is contained in:
Ethan Atkins 2019-01-31 13:56:13 -08:00
parent 16e7c70035
commit 9b40a0e585
1 changed files with 27 additions and 7 deletions

View File

@ -8,19 +8,22 @@
package sbt.internal.util
trait TypeFunctions {
import TypeFunctions._
type Id[X] = X
type NothingK[X] = Nothing
sealed trait Const[A] { type Apply[B] = A }
sealed trait ConstK[A] { type l[L[x]] = A }
sealed trait Compose[A[_], B[_]] { type Apply[T] = A[B[T]] }
sealed trait [A[_], B[_]] { type l[T] = A[B[T]] }
type AnyLeft[T] = Left[T, Nothing]
type AnyRight[T] = Right[Nothing, T]
final val left = λ[Id ~> Left[?, Nothing]](Left(_))
final val right = λ[Id ~> Right[Nothing, ?]](Right(_))
final val some = λ[Id ~> Some](Some(_))
final def idFun[T]: T => T = (t: T) => t
final def const[A, B](b: B): A => B = _ => b
final def idK[M[_]]: M ~> M = λ[M ~> M](m => m)
final val left = λ[Id ~> AnyLeft](Left(_)).setToString("TypeFunctions.left")
final val right = λ[Id ~> AnyRight](Right(_)).setToString("TypeFunctions.right")
final val some = λ[Id ~> Some](Some(_)).setToString("TypeFunctions.some")
final def idFun[T]: T => T = ((t: T) => t).setToString("TypeFunctions.id")
final def const[A, B](b: B): A => B = ((_: A) => b).setToString(s"TypeFunctions.const($b)")
final def idK[M[_]]: M ~> M = λ[M ~> M](m => m).setToString("TypeFunctions.idK")
def nestCon[M[_], N[_], G[_]](f: M ~> N): (M G)#l ~> (N G)#l =
f.asInstanceOf[(M G)#l ~> (N G)#l] // implemented with a cast to avoid extra object+method call.
@ -31,7 +34,24 @@ trait TypeFunctions {
type ~>|[A[_], B[_]] = A ~> Compose[Option, B]#Apply
}
object TypeFunctions extends TypeFunctions
object TypeFunctions extends TypeFunctions {
private implicit class Ops[T[_], R[_]](val underlying: T ~> R) extends AnyVal {
def setToString(string: String): T ~> R = new (T ~> R) {
override def apply[U](a: T[U]): R[U] = underlying(a)
override def toString: String = string
override def equals(o: Any): Boolean = underlying.equals(o)
override def hashCode: Int = underlying.hashCode
}
}
private implicit class FunctionOps[A, B](val f: A => B) extends AnyVal {
def setToString(string: String): A => B = new (A => B) {
override def apply(a: A): B = f(a)
override def toString: String = string
override def equals(o: Any): Boolean = f.equals(o)
override def hashCode: Int = f.hashCode
}
}
}
trait ~>[-A[_], +B[_]] { outer =>
def apply[T](a: A[T]): B[T]