diff --git a/build.sbt b/build.sbt index 3a156bd08..9b4de1a33 100644 --- a/build.sbt +++ b/build.sbt @@ -1,5 +1,4 @@ import com.typesafe.sbt.SbtGit.GitKeys._ -import sbtcrossproject.CrossPlugin.autoImport.crossProject import sbtcrossproject.CrossProject val Scala212 = "2.12.13" diff --git a/core/src/main/scala/shapeless/ops/functions.scala b/core/src/main/scala/shapeless/ops/functions.scala index 58d500a5c..f95132548 100644 --- a/core/src/main/scala/shapeless/ops/functions.scala +++ b/core/src/main/scala/shapeless/ops/functions.scala @@ -30,7 +30,13 @@ object function { } object FnToProduct extends FnToProductInstances { + type Aux[F, P] = FnToProduct[F] { type Out = P } def apply[F <: AnyRef](implicit fntop: FnToProduct[F]): Aux[F, fntop.Out] = fntop + + private[shapeless] def instance[F, P](toProduct: F => P): Aux[F, P] = new FnToProduct[F] { + type Out = P + def apply(f: F) = toProduct(f) + } } /** @@ -41,6 +47,12 @@ object function { trait FnFromProduct[F] extends DepFn1[F] with Serializable object FnFromProduct extends FnFromProductInstances { + type Aux[F, O] = FnFromProduct[F] { type Out = O } def apply[F](implicit fnfromp: FnFromProduct[F]): Aux[F, fnfromp.Out] = fnfromp + + private[shapeless] def instance[P, F](fromProduct: P => F): Aux[P, F] = new FnFromProduct[P] { + type Out = F + def apply(f: P) = fromProduct(f) + } } } diff --git a/core/src/main/scala/shapeless/ops/hlists.scala b/core/src/main/scala/shapeless/ops/hlists.scala index d2a795198..623f8c47b 100644 --- a/core/src/main/scala/shapeless/ops/hlists.scala +++ b/core/src/main/scala/shapeless/ops/hlists.scala @@ -788,13 +788,16 @@ object hlist { trait Tupler[L <: HList] extends DepFn1[L] with Serializable object Tupler extends TuplerInstances { + type Aux[L <: HList, T] = Tupler[L] { type Out = T } def apply[L <: HList](implicit tupler: Tupler[L]): Aux[L, tupler.Out] = tupler + private[shapeless] def instance[L <: HList, T](tuple: L => T): Aux[L, T] = new Tupler[L] { + type Out = T + def apply(l: L) = tuple(l) + } + implicit val hnilTupler: Aux[HNil, Unit] = - new Tupler[HNil] { - type Out = Unit - def apply(l: HNil): Out = () - } + instance(_ => ()) } /** diff --git a/core/src/main/scala/shapeless/sized.scala b/core/src/main/scala/shapeless/sized.scala index aac4ac452..52a60966d 100644 --- a/core/src/main/scala/shapeless/sized.scala +++ b/core/src/main/scala/shapeless/sized.scala @@ -221,29 +221,32 @@ object AdditiveCollection { import scala.collection.immutable.Queue import scala.collection.LinearSeq + private[this] val instance = + new AdditiveCollection[Any] {} + implicit def linearSeqAdditiveCollection[T]: AdditiveCollection[LinearSeq[T]] = - new AdditiveCollection[LinearSeq[T]] {} + instance.asInstanceOf[AdditiveCollection[LinearSeq[T]]] implicit def vectorAdditiveCollection[T]: AdditiveCollection[Vector[T]] = - new AdditiveCollection[Vector[T]] {} + instance.asInstanceOf[AdditiveCollection[Vector[T]]] implicit def arrayAdditiveCollection[T]: AdditiveCollection[Array[T]] = - new AdditiveCollection[Array[T]] {} + instance.asInstanceOf[AdditiveCollection[Array[T]]] implicit def stringAdditiveCollection: AdditiveCollection[String] = - new AdditiveCollection[String] {} + instance.asInstanceOf[AdditiveCollection[String]] implicit def listAdditiveCollection[T]: AdditiveCollection[List[T]] = - new AdditiveCollection[List[T]] {} + instance.asInstanceOf[AdditiveCollection[List[T]]] implicit def streamAdditiveCollection[T]: AdditiveCollection[LazyList[T]] = - new AdditiveCollection[LazyList[T]] {} + instance.asInstanceOf[AdditiveCollection[LazyList[T]]] implicit def queueAdditiveCollection[T]: AdditiveCollection[Queue[T]] = - new AdditiveCollection[Queue[T]] {} + instance.asInstanceOf[AdditiveCollection[Queue[T]]] implicit def defaultAdditiveCollection[T]: AdditiveCollection[collection.immutable.IndexedSeq[T]] = - new AdditiveCollection[collection.immutable.IndexedSeq[T]] {} + instance.asInstanceOf[AdditiveCollection[collection.immutable.IndexedSeq[T]]] } class DefaultToIndexedSeq[CC[_]] diff --git a/core/src/main/scala/shapeless/typeable.scala b/core/src/main/scala/shapeless/typeable.scala index 6cd5fb859..32fda4382 100644 --- a/core/src/main/scala/shapeless/typeable.scala +++ b/core/src/main/scala/shapeless/typeable.scala @@ -44,15 +44,18 @@ object Typeable extends TupleTypeableInstances with LowPriorityTypeable { import scala.reflect.ClassTag import syntax.typeable._ - def apply[T](implicit castT: Typeable[T]) = castT + def apply[T](implicit castT: Typeable[T]): Typeable[T] = castT // This is supported by type arguments on patterns, available in Typelevel Scala 4+ def unapply[T: Typeable](t: Any): Option[T] = t.cast[T] + private[shapeless] def instance[T](description: => String)(f: Any => Option[T]): Typeable[T] = new Typeable[T] { + def describe = description + def cast(t: Any) = f(t) + } + case class ValueTypeable[T, B](cB: Class[B], describe: String) extends Typeable[T] { - def cast(t: Any): Option[T] = { - if(t != null && cB.isInstance(t)) Some(t.asInstanceOf[T]) else None - } + def cast(t: Any): Option[T] = if (t != null && cB.isInstance(t)) Some(t.asInstanceOf[T]) else None } /** Typeable instance for `Byte`. */ @@ -87,58 +90,34 @@ object Typeable extends TupleTypeableInstances with LowPriorityTypeable { /** Typeable instance for `Any`. */ implicit val anyTypeable: Typeable[Any] = - new Typeable[Any] { - def cast(t: Any): Option[Any] = Some(t) - def describe = "Any" - } + instance("Any")(Some.apply) /** Typeable instance for `AnyVal`. */ - implicit val anyValTypeable: Typeable[AnyVal] = - new Typeable[AnyVal] { - def cast(t: Any): Option[AnyVal] = { - if(t != null && isValClass(t.getClass)) Some(t.asInstanceOf[AnyVal]) else None - } - def describe = "AnyVal" - } + implicit val anyValTypeable: Typeable[AnyVal] = instance("AnyVal") { t => + if (t != null && isValClass(t.getClass)) Some(t.asInstanceOf[AnyVal]) else None + } /** Typeable instance for `AnyRef`. */ - implicit val anyRefTypeable: Typeable[AnyRef] = - new Typeable[AnyRef] { - def cast(t: Any): Option[AnyRef] = { - if(t == null || isValClass(t.getClass)) None else Some(t.asInstanceOf[AnyRef]) - } - def describe = "AnyRef" - } + implicit val anyRefTypeable: Typeable[AnyRef] = instance("AnyRef") { t => + if (t == null || isValClass(t.getClass)) None else Some(t.asInstanceOf[AnyRef]) + } /** Typeable instance for simple monomorphic types */ - def simpleTypeable[T](erased: Class[T]): Typeable[T] = { + def simpleTypeable[T](erased: Class[T]): Typeable[T] = namedSimpleTypeable(erased, safeSimpleName(erased)) - } /** Typeable instance for simple monomorphic types, specifying the name explicitly */ - def namedSimpleTypeable[T](erased: Class[T], name: => String): Typeable[T] = - new Typeable[T] { - def cast(t: Any): Option[T] = { - if(t != null && erased.isInstance(t)) Some(t.asInstanceOf[T]) else None - } - def describe = name - } + def namedSimpleTypeable[T](erased: Class[T], name: => String): Typeable[T] = instance(name) { t => + if (t != null && erased.isInstance(t)) Some(t.asInstanceOf[T]) else None + } /** Typeable instance defined by a partial function and given an explicit name */ def partialFunctionTypeable[T](pf: PartialFunction[Any, T], name: => String): Typeable[T] = - new Typeable[T] { - val caster = pf.lift - def cast(t: Any) = caster(t) - def describe = name - } + instance(name)(pf.lift) /** Typeable instance for singleton value types */ def valueSingletonTypeable[T](value: T, name: String): Typeable[T] = - new Typeable[T] { - def cast(t: Any): Option[T] = - if(t == value) Some(value) else None - def describe = s"$name($value)" - } + instance(s"$name($value)")(t => if (t == value) Some(value) else None) /** Typeable instance for singleton reference types (not serializable by default) */ def referenceSingletonTypeable[T <: AnyRef](value: T, name: String): Typeable[T] = @@ -160,108 +139,83 @@ object Typeable extends TupleTypeableInstances with LowPriorityTypeable { */ def referenceSingletonTypeable[T <: AnyRef](value: T, name: String, serializable: Boolean): Typeable[T] = new Typeable[T] { + def describe = s"$name.type" def cast(t: Any): Option[T] = - if(t.asInstanceOf[AnyRef] eq value) Some(value) else None - - def describe = s"$name.type" + if (t.asInstanceOf[AnyRef] eq value) Some(value) else None @throws(classOf[java.io.IOException]) - private def writeObject(out: java.io.ObjectOutputStream): Unit = { + private def writeObject(out: java.io.ObjectOutputStream): Unit = if (serializable) out.defaultWriteObject() else throw new java.io.NotSerializableException("referenceSingletonTypeable") - } } /** Typeable instance for intersection types with typeable parents */ def intersectionTypeable[T](parents: Array[Typeable[_]]): Typeable[T] = - new Typeable[T] { - def cast(t: Any): Option[T] = { - if(t != null && parents.forall(_.cast(t).isDefined)) Some(t.asInstanceOf[T]) else None - } - def describe = parents map(_.describe) mkString " with " + instance(parents.map(_.describe).mkString(" with ")) { t => + if (t != null && parents.forall(_.cast(t).isDefined)) Some(t.asInstanceOf[T]) else None } /** Typeable instance for `Option`. */ implicit def optionTypeable[T](implicit castT: Typeable[T]): Typeable[Option[T]] = - new Typeable[Option[T]]{ - def cast(t: Any): Option[Option[T]] = { - if(t == null) None - else if(t.isInstanceOf[Option[_]]) { - val o = t.asInstanceOf[Option[_]] - if(o.isEmpty) Some(t.asInstanceOf[Option[T]]) - else for(e <- o; _ <- e.cast[T]) yield t.asInstanceOf[Option[T]] - } else None - } - def describe = s"Option[${castT.describe}]" + instance(s"Option[${castT.describe}]") { + case o: Option[_] => + if (o.isEmpty) Some(o.asInstanceOf[Option[T]]) + else for (e <- o; _ <- e.cast[T]) yield o.asInstanceOf[Option[T]] + case _ => + None } /** Typeable instance for `Either`. */ - implicit def eitherTypeable[A, B] - (implicit castA: Typeable[A], castB: Typeable[B]): Typeable[Either[A, B]] = - new Typeable[Either[A, B]] { - def cast(t: Any): Option[Either[A, B]] = { - t.cast[Left[A, B]] orElse t.cast[Right[A, B]] - } - def describe = s"Either[${castA.describe}, ${castB.describe}]" - } + implicit def eitherTypeable[A, B]( + implicit castA: Typeable[A], castB: Typeable[B] + ): Typeable[Either[A, B]] = instance(s"Either[${castA.describe}, ${castB.describe}]") { t => + t.cast[Left[A, B]] orElse t.cast[Right[A, B]] + } /** Typeable instance for `Left`. */ implicit def leftTypeable[A, B](implicit castA: Typeable[A]): Typeable[Left[A, B]] = - new Typeable[Left[A, B]] { - def cast(t: Any): Option[Left[A, B]] = { - if(t == null) None - else if(t.isInstanceOf[Left[_, _]]) { - val l = t.asInstanceOf[Left[_, _]] - for(a <- l.value.cast[A]) yield t.asInstanceOf[Left[A, B]] - } else None - } - def describe = s"Left[${castA.describe}]" + instance(s"Left[${castA.describe}]") { + case l: Left[_, _] => + for (_ <- l.value.cast[A]) yield l.asInstanceOf[Left[A, B]] + case _ => + None } /** Typeable instance for `Right`. */ implicit def rightTypeable[A, B](implicit castB: Typeable[B]): Typeable[Right[A, B]] = - new Typeable[Right[A, B]] { - def cast(t: Any): Option[Right[A, B]] = { - if(t == null) None - else if(t.isInstanceOf[Right[_, _]]) { - val r = t.asInstanceOf[Right[_, _]] - for(b <- r.value.cast[B]) yield t.asInstanceOf[Right[A, B]] - } else None - } - def describe = s"Right[${castB.describe}]" + instance(s"Right[${castB.describe}]") { + case r: Right[_, _] => + for (_ <- r.value.cast[B]) yield r.asInstanceOf[Right[A, B]] + case _ => + None } /** Typeable instance for `Traversable`. - * Note that the contents be will tested for conformance to the element type. */ - implicit def genTraversableTypeable[CC[X] <: Iterable[X], T] - (implicit mCC: ClassTag[CC[_]], castT: Typeable[T]): Typeable[CC[T] with Iterable[T]] = - // Nb. the apparently redundant `with Iterable[T]` is a workaround for a - // Scala 2.10.x bug which causes conflicts between this instance and `anyTypeable`. - new Typeable[CC[T]] { - def cast(t: Any): Option[CC[T]] = - if(t == null) None - else if(mCC.runtimeClass isInstance t) { - val cc = t.asInstanceOf[CC[Any]] - if(cc.forall(_.cast[T].isDefined)) Some(t.asInstanceOf[CC[T]]) - else None - } else None - def describe = s"${safeSimpleName(mCC)}[${castT.describe}]" - } + * Note that the contents be will tested for conformance to the element type. + */ + // Nb. the apparently redundant `with Iterable[T]` is a workaround for a + // Scala bug which causes conflicts between this instance and `anyTypeable`. + implicit def genTraversableTypeable[CC[X] <: Iterable[X], T]( + implicit mCC: ClassTag[CC[_]], castT: Typeable[T] + ): Typeable[CC[T] with Iterable[T]] = instance(s"${safeSimpleName(mCC)}[${castT.describe}]") { t => + if (t == null) None + else if (mCC.runtimeClass isInstance t) { + val cc = t.asInstanceOf[CC[Any]] + if (cc.forall(_.cast[T].isDefined)) Some(t.asInstanceOf[CC[T]]) else None + } else None + } /** Typeable instance for `Map`. Note that the contents will be tested for conformance to the key/value types. */ - implicit def genMapTypeable[M[X, Y], K, V] - (implicit ev: M[K, V] <:< Map[K, V], mM: ClassTag[M[_, _]], castK: Typeable[K], castV: Typeable[V]): Typeable[M[K, V]] = - new Typeable[M[K, V]] { - def cast(t: Any): Option[M[K, V]] = - if(t == null) None - else if(mM.runtimeClass isInstance t) { - val m = t.asInstanceOf[Map[Any, Any]] - if(m.forall(_.cast[(K, V)].isDefined)) Some(t.asInstanceOf[M[K, V]]) - else None - } else None - def describe = s"${safeSimpleName(mM)}[${castK.describe}, ${castV.describe}]" - } + implicit def genMapTypeable[M[X, Y], K, V]( + implicit ev: M[K, V] <:< Map[K, V], mM: ClassTag[M[_, _]], castK: Typeable[K], castV: Typeable[V] + ): Typeable[M[K, V]] = instance(s"${safeSimpleName(mM)}[${castK.describe}, ${castV.describe}]") { t => + if (t == null) None + else if (mM.runtimeClass isInstance t) { + val m = t.asInstanceOf[Map[Any, Any]] + if (m.forall(_.cast[(K, V)].isDefined)) Some(t.asInstanceOf[M[K, V]]) else None + } else None + } /** Typeable instance for polymorphic case classes with typeable elements */ def caseClassTypeable[T](erased: Class[T], fields: Array[Typeable[_]]): Typeable[T] = @@ -269,94 +223,65 @@ object Typeable extends TupleTypeableInstances with LowPriorityTypeable { /** Typeable instance for polymorphic case classes with typeable elements, specifying the name explicitly. */ def namedCaseClassTypeable[T](erased: Class[T], fields: Array[Typeable[_]], name: => String): Typeable[T] = - new Typeable[T] { - def cast(t: Any): Option[T] = - if(classOf[Product].isAssignableFrom(erased) && erased.isInstance(t)) { - val c = t.asInstanceOf[Product with T] - val f = c.productIterator.toList - if((f zip fields).forall { case (f, castF) => castF.cast(f).isDefined }) Some(c) - else None - } else None - def describe = { - val typeParams = fields map(_.describe) mkString(",") - s"$name[$typeParams]" - } + instance(s"$name[${fields.map(_.describe).mkString(",")}]") { t => + if (classOf[Product].isAssignableFrom(erased) && erased.isInstance(t)) { + val c = t.asInstanceOf[Product with T] + val f = c.productIterator.toList + if ((f zip fields).forall { case (f, castF) => castF.cast(f).isDefined }) Some(c) else None + } else None } /** Typeable instance for `HNil`. */ - implicit val hnilTypeable: Typeable[HNil] = - new Typeable[HNil] { - def cast(t: Any): Option[HNil] = if(t != null && t.isInstanceOf[HNil]) Some(t.asInstanceOf[HNil]) else None - def describe = "HNil" - } + implicit val hnilTypeable: Typeable[HNil] = instance("HNil") { t => + if (t != null && t.isInstanceOf[HNil]) Some(t.asInstanceOf[HNil]) else None + } /** Typeable instance for `HList`s. Note that the contents will be tested for conformance to the element types. */ - implicit def hlistTypeable[H, T <: HList](implicit castH: Typeable[H], castT: Typeable[T]): Typeable[H :: T] = - new Typeable[H :: T] { - def cast(t: Any): Option[H :: T] = { - if(t == null) None - else if(t.isInstanceOf[::[_, _ <: HList]]) { - val l = t.asInstanceOf[::[_, _ <: HList]] - for(hd <- l.head.cast[H]; tl <- (l.tail: Any).cast[T]) yield t.asInstanceOf[H :: T] - } else None - } - def describe = s"${castH.describe} :: ${castT.describe}" - } + implicit def hlistTypeable[H, T <: HList]( + implicit castH: Typeable[H], castT: Typeable[T] + ): Typeable[H :: T] = instance(s"${castH.describe} :: ${castT.describe}") { + case l: ::[_, _] => + for (_ <- l.head.cast[H]; _ <- (l.tail: Any).cast[T]) yield l.asInstanceOf[H :: T] + case _ => + None + } /** Typeable instance for `CNil`. */ implicit val cnilTypeable: Typeable[CNil] = - new Typeable[CNil] { - def cast(t: Any): Option[CNil] = None - def describe = "CNil" - } + instance("CNil")(_ => None) /** * Typeable instance for `Coproduct`s. * Note that the contents will be tested for conformance to one of the element types. */ - implicit def coproductTypeable[H, T <: Coproduct] - (implicit castH: Typeable[H], castT: Typeable[T]): Typeable[H :+: T] = - new Typeable[H :+: T] { - def cast(t: Any): Option[H :+: T] = { - t.cast[Inl[H, T]] orElse t.cast[Inr[H, T]] - } - def describe = s"${castH.describe} :+: ${castT.describe}" - } + implicit def coproductTypeable[H, T <: Coproduct]( + implicit castH: Typeable[H], castT: Typeable[T] + ): Typeable[H :+: T] = instance(s"${castH.describe} :+: ${castT.describe}") { t => + t.cast[Inl[H, T]] orElse t.cast[Inr[H, T]] + } /** Typeable instance for `Inl`. */ implicit def inlTypeable[H, T <: Coproduct](implicit castH: Typeable[H]): Typeable[Inl[H, T]] = - new Typeable[Inl[H, T]] { - def cast(t: Any): Option[Inl[H, T]] = { - if(t == null) None - else if(t.isInstanceOf[Inl[_, _ <: Coproduct]]) { - val l = t.asInstanceOf[Inl[_, _ <: Coproduct]] - for(hd <- l.head.cast[H]) yield t.asInstanceOf[Inl[H, T]] - } else None - } - def describe = s"Inl[${castH.describe}}]" + instance(s"Inl[${castH.describe}}]") { + case l: Inl[_, _] => + for (_ <- l.head.cast[H]) yield l.asInstanceOf[Inl[H, T]] + case _ => + None } /** Typeable instance for `Inr`. */ implicit def inrTypeable[H, T <: Coproduct](implicit castT: Typeable[T]): Typeable[Inr[H, T]] = - new Typeable[Inr[H, T]] { - def cast(t: Any): Option[Inr[H, T]] = { - if(t == null) None - else if(t.isInstanceOf[Inr[_, _ <: Coproduct]]) { - val r = t.asInstanceOf[Inr[_, _ <: Coproduct]] - for(tl <- r.tail.cast[T]) yield t.asInstanceOf[Inr[H, T]] - } else None - } - def describe = s"Inr[${castT.describe}}]" + instance(s"Inr[${castT.describe}}]") { + case r: Inr[_, _] => + for (_ <- r.tail.cast[T]) yield r.asInstanceOf[Inr[H, T]] + case _ => + None } // Workaround for https://issues.scala-lang.org/browse/SI-5425 private def safeSimpleName(erased: Class[_]): String = - try { - erased.getSimpleName - } catch { - case _: InternalError => - erased.getName - } + try erased.getSimpleName + catch { case _: InternalError => erased.getName } private def safeSimpleName(tag: ClassTag[_]): String = safeSimpleName(tag.runtimeClass) @@ -385,8 +310,8 @@ class TypeableMacros(val c: blackbox.Context) extends SingletonTypeUtils { import c.universe._ import definitions.NothingClass - val typeableTpe = typeOf[Typeable[_]].typeConstructor - val genericTpe = typeOf[Generic[_]].typeConstructor + val typeableTpe: Type = typeOf[Typeable[_]].typeConstructor + val genericTpe: Type = typeOf[Generic[_]].typeConstructor def dfltTypeableImpl[T: WeakTypeTag]: Tree = { val tpe = weakTypeOf[T] diff --git a/project/Boilerplate.scala b/project/Boilerplate.scala index 76057fd18..a2b959f21 100644 --- a/project/Boilerplate.scala +++ b/project/Boilerplate.scala @@ -138,18 +138,15 @@ object Boilerplate { |import hlist.Tupler | |trait TuplerInstances { - | type Aux[L <: HList, Out0] = Tupler[L] { type Out = Out0 } - - - implicit def hlistTupler${arity} - - [${`A..N`}] - - : Aux[ + - implicit def hlistTupler$arity[ + - ${`A..N`} + - ]: Tupler.Aux[ - ${`A::N`}, - ${`(A..N)`} - - ] = - - new Tupler[${`A::N`}] { - - type Out = ${`(A..N)`} - - def apply(l : ${`A::N`}): Out = l match { case ${`a::n`} => ${`(a..n)`} } - - } + - ] = Tupler.instance { case ${`a::n`} => + - ${`(a..n)`} + - } |} """ } @@ -164,7 +161,9 @@ object Boilerplate { import tv._ val fnType = s"(${`A..N`}) => Res" val hlistFnType = s"(${`A::N`}) => Res" - val fnBody = if (arity == 0) "fn()" else s"l match { case ${`a::n`} => fn(${`a..n`}) }" + val fnBody = + if (arity == 0) "_ => fn()" + else s"{ case ${`a::n`} => fn(${`a..n`}) }" block""" |package ops @@ -172,20 +171,13 @@ object Boilerplate { |import function.FnToProduct | |trait FnToProductInstances { - | type Aux[F, Out0] = FnToProduct[F] { type Out = Out0 } - - - implicit def fnToProduct${arity} - - [${`A..N,Res`}] - - : Aux[ - - (${fnType}), - - ${hlistFnType} - - ] = - - new FnToProduct[${fnType}] { - - type Out = ${hlistFnType} - - def apply(fn: ${fnType}): Out - - = (l : ${`A::N`}) - - => ${fnBody} - - } + - implicit def fnToProduct$arity[ + - ${`A..N,Res`} + - ]: FnToProduct.Aux[ + - ($fnType), + - $hlistFnType + - ] = FnToProduct.instance(fn => $fnBody) |} """ } @@ -207,21 +199,16 @@ object Boilerplate { |import function.FnFromProduct | |trait FnFromProductInstances { - | type Aux[F, Out0] = FnFromProduct[F] { type Out = Out0 } - | - - implicit def fnFromProduct${arity} - - [${`A..N,Res`}] - - : Aux[ - - ${hlistFnType}, - - ${fnType} - - ] = - - new FnFromProduct[${hlistFnType}] { - - type Out = ${fnType} - - def apply(hf : ${hlistFnType}): Out - - = (${`a:A..n:N`}) - - => hf(${`a::n`}) - - } - + - implicit def fnFromProduct$arity[ + - ${`A..N,Res`} + - ]: FnFromProduct.Aux[ + - $hlistFnType, + - $fnType + - ] = FnFromProduct.instance { hf => + - (${`a:A..n:N`}) => + - hf(${`a::n`}) + - } |} """ } @@ -305,24 +292,20 @@ object Boilerplate { |trait Cases { | import poly._ | - - type Case${arity}[Fn, ${`A..N`}] - - = Case[Fn, ${`A::N`}] + - type Case$arity[Fn, ${`A..N`}] = + - Case[Fn, ${`A::N`}] - - - object Case${arity} { - - type Aux[Fn, ${`A..N`}, Result0] - - = Case[Fn, ${`A::N`}] { type Result = Result0 } + - object Case$arity { + - type Aux[Fn, ${`A..N`}, Result0] = + - Case[Fn, ${`A::N`}] { type Result = Result0 } - - - def apply - - [Fn, ${`A..N`}, Result0] - - (fn: (${`A..N`}) => Result0) - - : Aux[Fn, ${`A..N`}, Result0] = - - new Case[Fn, ${`A::N`}] { - - type Result = Result0 - - val value = (l: ${`A::N`}) - - => l match { - - case ${`a::n`} => - - fn(${`a..n`}) - - } + - def apply[ + - Fn, ${`A..N`}, Result0 + - ]( + - fn: (${`A..N`}) => Result0 + - ): Aux[Fn, ${`A..N`}, Result0] = + - Case { case ${`a::n`} => + - fn(${`a..n`}) - } - } - @@ -337,35 +320,36 @@ object Boilerplate { def content(tv: TemplateVals) = { import tv._ - val fnBody = if (arity == 0) "fn()" else s"l match { case ${`a::n`} => fn(${`a..n`}) }" + + val fnBody = + if (arity == 0) "_ => fn()" + else s"{ case ${`a::n`} => fn(${`a..n`}) }" block""" | - - -trait Poly${arity} extends Poly { outer => - - type Case[${`A..N`}] - - = poly.Case[this.type, ${`A::N`}] + -trait Poly$arity extends Poly { outer => + - type Case[${`A..N`}] = + - poly.Case[this.type, ${`A::N`}] - - object Case { - - type Aux[${`A..N`}, Result0] - - = poly.Case[outer.type, ${`A::N`}] { type Result = Result0 } + - type Aux[${`A..N`}, Result0] = + - poly.Case[outer.type, ${`A::N`}] { type Result = Result0 } - } - - - class CaseBuilder${arity}[${`A..N`}] { - - def apply[Res] - - (fn: (${`A..N`}) => Res) = new Case[${`A..N`}] { - - type Result = Res - - val value = (l: ${`A::N`}) - - => ${fnBody} - - } + - class CaseBuilder$arity[${`A..N`}] { + - def apply[Res]( + - fn: (${`A..N`}) => Res + - ): Case.Aux[${`A..N`}, Res] = + - poly.Case($fnBody) - } - - - def at[${`A..N`}] - - = new CaseBuilder${arity}[${`A..N`}] + - def at[${`A..N`}] = + - new CaseBuilder$arity[${`A..N`}] -} - - -object Poly${arity} extends PolyNBuilders.Poly${arity}Builder[HNil] { - - val functions = HNil + -object Poly$arity extends PolyNBuilders.Poly${arity}Builder[HNil] { + - val functions = HNil -} | """ @@ -414,15 +398,18 @@ object Boilerplate { - } - - object Function${arity}TypeAt { - - implicit def at0[${`A..N`}, Out, Tail <: HList]: Function${arity}TypeAt[${`A..N`}, Out, ((${`A..N`}) => Out)::Tail] = - - new Function${arity}TypeAt[${`A..N`}, Out, ((${`A..N`}) => Out)::Tail] { - - def apply(l: ((${`A..N`}) => Out)::Tail): (${`A..N`}) => Out = l.head - - } - - - implicit def atOther[${`A..N`}, Out, Tail <: HList, Head](implicit tprev: Function${arity}TypeAt[${`A..N`}, Out, Tail]): Function${arity}TypeAt[${`A..N`}, Out, Head::Tail] = - - new Function${arity}TypeAt[${`A..N`}, Out, Head::Tail] { - - def apply(l: Head::Tail): (${`A..N`}) => Out = tprev(l.tail) - - } + - implicit def at0[ + - ${`A..N`}, Out, Tail <: HList + - ]: Function${arity}TypeAt[${`A..N`}, Out, ((${`A..N`}) => Out) :: Tail] = + - _.head + - + - implicit def atOther[ + - ${`A..N`}, Out, Tail <: HList, Head + - ]( + - implicit tprev: Function${arity}TypeAt[${`A..N`}, Out, Tail] + - ): Function${arity}TypeAt[${`A..N`}, Out, Head :: Tail] = + - l => tprev(l.tail) - } |} """ @@ -450,30 +437,28 @@ object Boilerplate { def content(tv: TemplateVals) = { import tv._ - val implicitArgs = (synTypes map(a => s"cast${a}:Typeable[${a}]")) mkString ", " - val enumerators = synTypes.zipWithIndex map { case (a,idx) => s"_ <- p._${idx+1}.cast[${a}]" } mkString "; " - val castVals = (synTypes map(a => s"$${cast${a}.describe}")) mkString ", " + + val implicitArgs = synTypes.map(a => s"cast$a:Typeable[$a]").mkString(", ") + val enumerators = synTypes.zipWithIndex.map { case (a, i) => s"_ <- p._${i+1}.cast[$a]" }.mkString("; ") + val castVals = synTypes.map(a => s"$${cast$a.describe}").mkString(", ") block""" | |trait TupleTypeableInstances { | import syntax.typeable._ - | - - implicit def tuple${arity}Typeable - - [${`A..N`}] - - (implicit ${implicitArgs}) - - = new Typeable[${`(A..N)`}] { - - def cast(t : Any) : Option[${`(A..N)`}] = { - - if(t == null) None - - else if(t.isInstanceOf[${`(_.._)`}]) { - - val p = t.asInstanceOf[${`(_.._)`}] - - for(${enumerators}) - - yield t.asInstanceOf[${`(A..N)`}] - - } else None - - } - - override def describe = s"($castVals)" - - } - + - implicit def tuple${arity}Typeable[ + - ${`A..N`} + - ]( + - implicit $implicitArgs + - ): Typeable[${`(A..N)`}] = + - Typeable.instance(s"($castVals)") { + - case p: ${`(_.._)`} => + - for ($enumerators) + - yield p.asInstanceOf[${`(A..N)`}] + - case _ => + - None + - } |} """ } @@ -548,6 +533,6 @@ object Boilerplate { -} | """ - } + } } }