2

(簡略化された)特性のインスタンスを具体化しようとしています

trait TC[F[_]] {
  def apply[A](fa: F[A]): F[A]
}

Scala マクロの使用。したがって、マクロのシグネチャは次のとおりです。

def materialize[F[_]](c: Context)(
  implicit fT: c.WeakTypeTag[F[_]]): c.Expr[TC[F]]

次の 2 つの理由から、型コンストラクターF[_]を型パラメーターに適用する必要があります。A

  1. apply上記の署名を特定のFもの ( などFoo[A])に書き込むには
  2. Foo[A]興味深い本体を指定するために型のメンバーを検査するにはapply

Aで使用できるメソッド型パラメーターに対応する型を作成する方法はありますappliedTypeか? applyメソッドとその型パラメーターAもツリーとして生成されているだけなので、私には難しいようです。


マクロ呼び出しへの追加引数として取得しようとしWeakTypeTag[TC[F]]ましたが、パラメーターの型を受け取りました

val paramT = wfg.tpe.member("apply": TermName).tpe.typeParams.head.tpe

しかし、paramTinを使用するとq"... def apply[$paramT] ..."

java.lang.IllegalArgumentException: can't splice "A" as type parameter

したがって、これも解決策ではないようです。

4

1 に答える 1

0

上記の特性の定義を次のように変更することで問題を解決しました

trait TC[F[_]] {
  type ApplyF[A] = F[A]
  def apply[A](fa: ApplyF[A]): ApplyF[A]
}

ダミー値のツリーのタイプチェック:

typecheck(q"""new TC[Foo] {
  def apply[A](fa: ApplyF[A]): ApplyF[A] = ???
}""").tpe

型チェックされた結果は、(ツリー トランスフォーマーを使用して) 破壊および変換され、???. これは問題を完全には解決せず、型エラーが発生しました:

found   : A(in method apply)(in method apply)(in method apply)...
required: A(in method apply)(in method apply)(in method apply)...

ツリーを返す前に呼び出すuntypecheckことは役に立ちませんでしたが、結果のツリーを調べたところ、予想される結果が有効 (正しい型) の Scala コードであることが示されました。したがって、マクロを最終的に動作させる最後のステップは、

parse(showCode(result))

これは完全に不必要に感じますが、競合する型情報を取り除く唯一の方法だったようです。

于 2014-08-08T00:17:40.727 に答える