Скажем, у меня есть пустой маркер черты имени Marker
и некоторые функции с параметрами типа связанными Marker
:Почему эта функция Scala компилируется, когда аргумент не соответствует типу ограничения?
trait Marker
object Marker {
def works[M <: Marker](m:M):M = m
def doesntWork[M <: Marker](f:M => String):String = "doesn't matter"
}
Первая функция работает, как я ожидал. То есть, если вы передаете параметр, который не является Marker
, то код не компилируется:
scala> works("a string")
<console>:14: error: inferred type arguments [String] do not conform to method works's type parameter bounds [M <: com.joescii.Marker]
works("a string")
^
<console>:14: error: type mismatch;
found : String("a string")
required: M
works("a string")
^
Однако, я могу передать параметр для второй функции, которая не соответствует Marker
. В частности, я могу передать функцию типа String => String
и код счастливо компилируется и работает:
scala> doesntWork((str:String) => "a string")
res1: String = doesn't matter
Я ожидал бы этот вызов doesntWork
, чтобы не компилировать. Может ли кто-нибудь объяснить мне, почему он компилируется и как я могу изменить подпись функции, чтобы предотвратить проверку типов в таких случаях?
Полное раскрытие информации: вышеупомянутый надуманный пример представляет собой упрощенную версию this outstanding issue for lift-ng.
Но OP проходит '(str: String) =>« строка »' как аргумент - это не тип 'Any => String' (и любой подтип этого)? – chi
это неправильно, проверьте ответ @ larsrh – kosii
Это все еще полезно. Я не думал о том, что 'M => String' на самом деле' Function1 [M, String] ', который мог бы отключить мой ментальный флаг для рассмотрения контравариантности. Я знаком с концепцией, но я, конечно, все еще не знаю. :) – joescii