2010-05-16 3 views
3

Почему вызов fn (Iterator («foo») компилируется, но вызов fn (fooIterator) завершается с ошибкой «тип несоответствия: найдено: Iterator [java.lang.String] требуется: scala.Iterator [ com.banshee.Qx.HasLength] "В чем разница между этими двумя вызовами функции, использующей набор структурных типов?

object Qx { 
    type HasLength = {def length: Int} 
    def fn(xs: Iterator[HasLength]) = 3 
    var tn = fn(Iterator("foo")) 
    var fooIterator = Iterator("foo") 
    var tnFails = fn(fooIterator) //doesn't compile 
} 

Разве они не то же самое

+0

Можете ли вы опубликовать тип сингларов итераторов? Могут ли быть аннотации или импликации различий? – Dario

+0

Это всего лишь стандартный материал библиотеки, дополнительный код не требуется. Скала> Итератор («Foo») res0: Итератор [java.lang.String] = непустой итератор –

ответ

3

Это должно быть ошибка в представлении уточнения, поскольку следующие два формула оба работают.

object Qx1 { 
    // give length() parens, even though the Iterator definition doesn't have them 
    type HasLength = { def length(): Int } 

    def fn(xs: Iterator[HasLength]) = 3 
    var tn = fn(Iterator("foo")) 
    var fooIterator = Iterator("foo") 
    var tnFails = fn(fooIterator) //doesn't compile 
} 

object Qx2 { 
    type HasLength = { def length: Int } 

    def fn(xs: Iterator[HasLength]) = 3 
    var tn = fn(Iterator("foo")) 
    // annotate the type of fooIterator before the type inferencer can mis-infer 
    var fooIterator: Iterator[HasLength] = Iterator("foo") 
    var tnFails = fn(fooIterator) //doesn't compile 
} 

Edit:

Слишком рано утром. Это String с методом length(), который имеет parens, что означает, что он прав, и вы ошибаетесь, поскольку длина мышью и длина() - это один и тот же метод. (Это хорошая небольшая ловушка, которую я уже зарегистрировал ранее.)

+0

Если это просто длина v. Length(), не должен ли его первый пример потерпеть неудачу? var tn = fn (Iterator ("foo")) –

+0

И почему версия Рэндалла Шульца работает с проекцией зрения? Я немного озадачен. –

+1

Это просто длина по отношению к длине. fn (Итератор («foo»)) работает по той же причине, аннотируя тип работы fooIterator: ожидаемый тип выражения влияет на предполагаемый тип. В примере с ошибкой в ​​декларации выводится несовместимый тип, а затем вызов выполняется в отдельном заявлении. – extempore

3

Этот препарат работает:

object Qx { 
    type HasLength = {def length: Int} 
    def fn[HL <% HasLength](xs: Iterator[HL]) = 3 
    val tn = fn(Iterator("foo")) 
    val fooIterator = Iterator("foo") 
    val tnFails = fn(fooIterator) 
} 
+0

Я хотел бы унифицированное объяснение этого комментария и комментарий экспромтом по поводу нулевого аргумента длина-VS- длина-с пустыми круглыми скобками. У меня есть ощущение, что здесь происходит что-то тонкое, что я не понимаю. –