trait F[T] { type Out }
object F {
type Aux[T, out] = F[T] { type Out = out }
}
def glhf[t, out](implicit f: F.Aux[t, out]): out = ???
私は、これは、抽出のいずれかの種類(さえ複雑なクロス暗黙の型変数)のための魔法のように動作し、暗黙のパラメータ(ラ・型崩れ)の抽象型メンバーを抽出しようとしています。
ただし、抽象型メンバーが型のコンストラクタであり、単純型ではない場合、コンパイラは呼び出しポイントで型変数を統一することができません。
私は奇妙なコンパイルエラーがある小さなテストケースを作成しました。コンパイラのエラーはあまり意味を持たないので、私はこれがコンパイラのバグかどうか疑問に思っていますか?エラーメッセージの詳細については、コードサンプルを参照してください。
余分なメッセージはscala-2.12.4
,-Xlog-implicits
、さらに問題の場合は-Ypartial-unification
でコンパイルされます。
incubator/Main.scala
package incubator
object wat {
/**
* A "type class", "implicit evidence" type, etc...
*
* @tparam t just for looks, and facilitate
* the implicit resolution scenario
*/
trait fo[t] {
/**
* An abstract type member THAT IS A TYPE CONSTRUCTOR
*/
type f[_]
}
//
// Types that will be used for `fo`'s abstract type `f[_]`
//
trait F1[t]
trait F2[t]
//
// Couple of case for type class `fo`
//
trait loo
implicit object loo extends loo with fo[loo] {
type f[t] = F1[t]
}
//
trait poo
implicit object poo extends poo with fo[poo] {
type f[t] = F2[t]
}
// Double checking, this compiles
val w0 = implicitly[ fo[loo] ]
val w1 = implicitly[ fo[poo] ]
/**
* *** PROBLEM HERE ***
*
* A method call, in which the abstract TYPE CONSTRUCTOR type member
* needs to be inferred by the compiler.
*
* This fails to be implicitly resolved, because the compiler
* fails to instantiate the type parameters, (probably) because
* it is unable to infer abstract type `f`. See further below
* for the failed invocation.
*
*/
def fu0[t, in[_]](t: t)(
implicit
fo: fo[t] { type f[a] = in[a] }
): String = s"Hi $t: $fo"
// These will work fine, since we explicitly set type param `in`
val w2 = fu0[loo, F1](loo: loo)
val w3 = fu0[poo, F2](poo: poo)
// *** PROBLEM HERE ***
// The following fails to compile
val w4 = fu0(loo: loo) // type ascription for test simplification
val w5 = fu0(poo: poo) // type ascription for test simplification
//
// Error message:
//
// (notice the "type f has one type parameter, but type in has one"
// part of the error)
//
// [info] .../incubator/Main.scala:64:15: poo is not a valid implicit value for incubator.wat.fo[incubator.wat.poo]{type f[a] = in[a]} because:
// [info] type parameters weren't correctly instantiated outside of the implicit tree: inferred kinds of the type arguments (incubator.wat.poo.f[t]) do not conform to the expected kinds of the type parameters (type in).
// [info] incubator.wat.poo.f[t]'s type parameters do not match type in's expected parameters:
// [info] type f has one type parameter, but type in has one
// [info] val w5 = fu0(poo: poo) // type ascription for test simplification
// [info] ^
// [info] .../incubator/Main.scala:64:15: incubator.this.wat.poo is not a valid implicit value for incubator.wat.fo[incubator.wat.poo]{type f[a] = in[a]} because:
// [info] type parameters weren't correctly instantiated outside of the implicit tree: inferred kinds of the type arguments (incubator.wat.poo.f[t]) do not conform to the expected kinds of the type parameters (type in).
// [info] incubator.wat.poo.f[t]'s type parameters do not match type in's expected parameters:
// [info] type f has one type parameter, but type in has one
// [info] val w5 = fu0(poo: poo) // type ascription for test simplification
// [info] ^
// [error] .../incubator/Main.scala:64:15: could not find implicit value for parameter fo: incubator.wat.fo[incubator.wat.poo]{type f[a] = in[a]}
// [error] val w5 = fu0(poo: poo) // type ascription for test simplification
// [error] ^
// [error] two errors found
// [error] (compile:compileIncremental) Compilation failed
// [error] Total time: 1 s, completed Oct 22, 2017 4:48:35 PM
//
}
おかげで、しかし、あなたはポイントをmenitonとして_ [におけるその型パラメータ 'であります] 'がメソッドのシグネチャで再利用されます。あなたのソリューションは、型変数をシグネチャから単に削除します。このユースケースを指定するには、その質問に明確化が必要です。再度、感謝します。 –
包括的なテストケースを作成するときにコメントにタグを付けてください:) –