Вопрос по generics, collections, scala, type-theory, functional-programming – Функция, которая обычно принимает тип и возвращает тот же тип

6

Мне трудно понять, почему компилятор Scala недоволен этим определением функции:

<code>def trimNonWordCharacters[T <: Iterable[String]](items: T): T =
     items map { _.replaceAll("\\W", "") }
</code>

ЗдесьРЕПЛ выход:

<code>scala> def trimNonWordCharacters[T <: Iterable[String]](items: T): T =
     items map { _.replaceAll("\\W", "") }
<console>:5: error: type mismatch;
 found   : Iterable[java.lang.String]
 required: T
       def trimNonWordCharacters[T <: Iterable[String]](items: T): T = items map { _.replaceAll("\\W", "") }
</code>

Цель состоит в том, чтобы передать любую реализацию Iterable и получить тот же тип возврата. Это возможно?

@LuigiPlinge этот вопрос не нуженCanBuildFrom, посколькуfilter не требует этого. Этот вопрос очень похож, иtitle этот вопрос, конечно, охватывает его, но здесь нужно сделать немного больше, чтобы он заработал. Daniel C. Sobral

Ваш Ответ

2   ответа
14

map метод наIterable возвращаетIterableтак что даже еслиT это подклассIterableэтоmap метод вернетсяIterable.

Чтобы лучше печатать, вы должны написать это так:

import scala.collection.IterableLike
def trimNonWordCharacters[T <: Iterable[String]](items: T with IterableLike[String, T]): T =
     items map { _.replaceAll("\\W", "") }

Однако это тоже не сработает, потому что нет информации, позволяющей отображать карту наT создать другойT, Например, отображениеBitSet вString не может привести кBitSet, Поэтому нам нужно что-то еще: что-то, что учит, как построитьT изTгде сопоставленные элементы имеют типString, Как это:

import scala.collection.IterableLike
import scala.collection.generic.CanBuildFrom
def trimNonWordCharacters[T <: Iterable[String]]
                         (items: T with IterableLike[String, T])
                         (implicit cbf: CanBuildFrom[T, String, T]): T =
     items map { _.replaceAll("\\W", "") }
Большое спасибо. Ваше объяснение очень информативно, и теперь я наконец-то знаю, как его использовать.CanBuildFrom (!) Jay Taylor
0

[Entering as an answer rather than a comment because code in comments doesn't format properly]

@Daniel, спасибо за объяснение, я также нашел это полезным. Поскольку Iterable является производным от IterableLike, похоже, что следующее работает и немного более компактно:

import scala.collection.IterableLike
import scala.collection.generic.CanBuildFrom
def trimNonWordCharacters[T <: IterableLike[String, T]]
 (items: T)
 (implicit cbf: CanBuildFrom[T, String, T]): T =
 items map { _.replaceAll("\\W", "") }

Похожие вопросы