У меня возникла странная ошибка компилятора о неявной, которая на самом деле присутствует, но не может быть найден по какой-либо причине. Поэтому я создал небольшой тестовый пример, который воспроизводит таинственное поведение.Почему в некоторых случаях игнорируются случаи высокого порядка?
trait Hide {
type T
}
object HideString extends Hide {
override type T = String
}
object HideBool extends Hide {
override type T = Boolean
}
Простой тип используется как однозначная цель для неявных преобразований.
def id[H <: Hide, C](x : C)(implicit ev : C => H#T) : H#T = ev(x)
def drop[H <: Hide, C](x : C)(implicit ev : C => H#T) : Int = {
println(ev(x))
1
}
def idSeq[H <: Hide, C](x : Seq[C])(implicit ev : Seq[C] => Seq[H#T]) : Seq[H#T] = ev(x)
def dropSeq[H <: Hide, C](x : Seq[C])(implicit ev : Seq[C] => Seq[H#T]) : Int = {
println(ev(x))
1
}
Методы, основанные на неявных преобразованиях. Это в основном матрица 2x2. id
методы возвращают преобразованный тип и методы drop
используют преобразование внутри и возвращают некоторую константу. Нормальные методы действуют на точный неявно преобразованный тип, а методы Seq
работают с последовательностями.
implicit def exString(x : String) : HideString.type#T = x
implicit def highString[F[_]](x : F[String]) : F[HideString.type#T] = x
Над неявных преобразований highString
определяется с типом высшего порядка.
val s1 = id("sdf")
val s2 = drop("aero")
val r1 = idSeq(Seq("a", "bc"))
val r2 = dropSeq(Seq("i", "IO"))
Попытка фактически использовать преобразования приносит мне ошибку:
ImplicitResolution.scala:98: error: No implicit view available from Seq[String] => Seq[test.implicits.HighReduction.Hide#T].
val r2 = dropSeq(Seq("i", "IO"))
Это может быть суммированы в следующей матрице:
| | id | drop |
|--------+------+------|
| normal | pass | pass |
| seq | pass | fail |
Если я использую точно определенную неявное преобразование для dropSeq
метода он обычно встречается:
implicit def seqBool(x : Seq[Boolean]) : Seq[HideBool.type#T] = x
val a1 = idSeq(Seq(true, false))
val a2 = dropSeq(Seq(false, true))
И кроме того, если я явно указать неявный аргумент dropSeq
начал работать:
val r2i = dropSeq(Seq("i", "IO"))(highString[Seq] _)
И это самое странное. highString
неявно соответствует всем требованиям. И объявлено как implicit
, поэтому он должен быть найден компилятором. А в случае idSeq
он действительно найден. Итак, почему это проигнорировано в случае с dropSeq
?
Я был бы более склонен наградить вас щедростью, если бы вы представили проблему для «углового случая в компиляторе Scala», который вы описываете. Я предположил, что это был какой-то угловой случай, но вы все еще не предоставили достаточной информации для меня, чтобы узнать, является ли это ожидаемым * поведением, или если это действительно ошибка в компиляторе. Было бы также неплохо, если бы вы избавились от этого болтающегося '}' ... – DaoWen
Ваши две функции имеют одну и ту же подпись, кроме типа возврата, но вы используете вывод типа для r1 и r2 (поэтому тип возврата не может использоваться для неявного разрешения). Если можно разрешить неявное для r1 с доступной информацией о типе, можно разрешить неявное для r2: учитывая, что функция drop works и dropSeq этого не делает, вполне вероятно, что проблема связана с общими типами и типами. – Edmondo1984
Использование '-Xlog-implicits' дает некоторые интересные ошибки. –