Отсутствует ошибка типа параметра, вызывая toSet?

Попытка создать из списка символов список уникальных символов, отображаемых на их частоте - например. что-то вроде:

List('a','b','a') -> List(('a',2), ('b',1))

Итак, просто в консоли, это работает:

val l = List('a', 'b', 'c', 'b', 'c', 'a')       
val s = l.toSet                                  
s.map(i => (i, l.filter(x => x == i).size))

но укорачивание путем объединения двух последних строк не происходит?

l.toSet.map(i => (i, l.filter(x => x == i).size)) 

дает ошибку "отсутствующий тип параметра".

Может кто-нибудь объяснить, почему Scala жалуется на этот синтаксис?

Ответ 1

Когда вы говорите val s = l.toSet, компилятор показывает, что единственным разумным типом для toSet является Char - самый конкретный выбор. Тогда, учитывая, что s представляет собой набор из Char, компилятор понимает, что карта должна быть от Char.

Но во втором случае он не судит о том, что такое тип элементов в toSet. Это может быть Char, но AnyVal также будет работать, как и Any.

l.toSet.map((i: Any) => (i, l.filter(x => x == i).size))

Обычно правило заключается в том, что компилятор должен выбрать наиболее определенное значение. Но поскольку функции являются контравариантными в своем аргументе, они наиболее специфичны, когда они принимают Any как аргумент, поэтому компилятор не может решить. Там может существовать правило, чтобы разорвать галстук ( "предпочитают раннее предположение" ), но этого не существует. Поэтому он просит вашу помощь.

Вы можете указать тип либо в аргументе функции, либо в toSet, чтобы устранить проблему:

l.toSet.map((i: Char) => (i, l.filter(x => x == i).size))
l.toSet[Char].map(i => (i, l.filter(x => x == i).size))

Ответ 2

Добавление типа [ Char] в toSet делает трюк.

scala> l.toSet[Char].map(i => (i, l.filter(x => x == i).size))
scala.collection.immutable.Set[(Char, Int)] = Set((a,2), (b,2), (c,2))