类型宏已死:如何从定义计算类型?

时间:2013-10-23 08:48:42

标签: scala types compilation scala-macros dynamic-compilation

类型宏已关闭。

但是我有两个重要的用例需要它们。结果是我的应用程序中的可扩展性严重丧失。 两者都是给定其他类型的类型的动态编译时生成。 基本上我想做一些事情(显然不是scala代码,但我认为你会得到这个想法):

type T[U] = macro usecase1[U]

def usecase1[U]= U match {  
  case t if (t <:< Int) => String
  case ... => ...
}

第二个用例是:

type Remaining[A, B >: A] = macro ...

例如

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) 

我没有用宏来做这些假设。我打算现在就去做..直到我看到那种类型的宏已经死了。 无论如何,有没有人知道获得这些功能的技巧? 感谢

1 个答案:

答案 0 :(得分:1)

据我所知,第一个用例确实可以在某种程度上实现。以下是一个示例:

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

但是:

scala> implicitly[U =:= String]
<console>:19: error: Cannot prove that U =:= String.
              implicitly[U =:= String]
                        ^

另一方面:

scala> implicitly[bound1.Type =:= String]
res0: =:=[bound1.Type,String] = <function1>

隐含的解决方案似乎正在失去一些类型。不知道为什么,以及如何解决这个问题。


对于第二个用例,我会立即想到HList。类似的东西:

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

不知道如何将生成的HList组合成复合类型。像(伪代码):

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
}