Reputation: 169
Type macros are off.
However I have two important use cases that would have required them. The result is an important lost of extensibility in my application. Both are dynamic compile time generation of a type given other types. Basically i want to do something like (obviously not scala code but i think you'll get the idea) :
type T[U] = macro usecase1[U]
def usecase1[U]= U match {
case t if (t <:< Int) => String
case ... => ...
}
Second use case is :
type Remaining[A, B >: A] = macro ...
where for example
class C
trait T1 extends C
trait T2 extends C
type Remaining[C with T1 with T2, T2] is assigned to "C with T1" at compile time
(so the macro would have generated the subclass list, and generated a new type from the list without T2)
I didn't do it with macros so that are assumptions. I planned to do it now.. till i saw that type macro were dead. Anyway, did anyone knows a trick to obtain such functionalities? Thanks
Upvotes: 1
Views: 186
Reputation: 8378
The first use case is indeed implementable with implicits to some degree, as far as I understand it. Here's an example of how this might look like:
scala> trait Bound[A] {
| type Type
| }
defined trait Bound
scala> implicit val bound1 = new Bound[Int] { type Type = String }
bound1: Bound[Int]{type Type = String}
scala> implicit val bound2 = new Bound[String] { type Type = Double }
bound2: Bound[String]{type Type = Double}
scala> val tpe = implicitly[Bound[Int]]
tpe: Bound[Int] = $anon$1@2a6b3a99
scala> type U = tpe.Type
defined type alias U
But then:
scala> implicitly[U =:= String]
<console>:19: error: Cannot prove that U =:= String.
implicitly[U =:= String]
^
On the other hand:
scala> implicitly[bound1.Type =:= String]
res0: =:=[bound1.Type,String] = <function1>
Implicit resolution seems to be losing some types on the way. Not sure why, and how to work around that.
For the second use case, HList
s immediately come to mind. Something like:
scala> trait Remaining[A <: HList, B] { type Result = Remove[A, B] }
defined trait Remaining
scala> new Remaining[C :: T1 :: T2 :: HNil, T2] {}
res5: Remaining[shapeless.::[C,shapeless.::[T1,shapeless.::[T2,shapeless.HNil]]],T2] = $anon$1@3072e54b
Not sure how to combine the resulting HList
into a compound type though. Something like (pseudo-code):
trait Remaining[A <: HList, B] {
def produceType(
implicit ev0 : Remove.Aux[A, B, C],
ev1 : IsCons.Aux[C, H, T],
ev2 : LeftFolder[T, H, (T1, T2) => T1 with T2]) = ev2
// ^ Not real syntax, type-level function to combine/mix types
val tpe = produceType
type Result = tpe.Out
}
Upvotes: 1