scala: ошибка несоответствия типов - найдено T, требуется строка - PullRequest
4 голосов
/ 23 декабря 2011

Я изучаю scala, и этот вопрос может быть глупым, но ... почему?

Например, это нормально:

def matchList(ls: List[Int]): List[Int] = ls match {
  case 1 :: rest => rest
  case a :: b :: rest => (a + b) :: rest
  case _ => ls
}

matchList: (ls: List[Int])List[Int]

Но функция с параметром типа делаетне компилируется:

def matchList[T](ls: List[T]): List[T] = ls match {
  case 1 :: rest => rest
  case a :: b :: rest => (a + b) :: rest
  case _ => ls
}

<console>:10: error: type mismatch;
found   : T
required: String
   case a :: b :: rest => (a + b) :: rest

Почему?

Ответы [ 3 ]

9 голосов
/ 23 декабря 2011

Для любого типа T операция T + T не имеет никакого смысла.(Все типы поддерживают +? Нет. Подумайте о добавлении двух собак или двух сотрудников.)

В вашем случае вызывается оператор конкатенации строк (добавляется через any2stringadd pimp), тип возвращаемого значенияявляется (очевидно) String.Отсюда и сообщение об ошибке.

Вам нужен способ указать, что тип T должен поддерживать операцию, в которой вы комбинируете два значения типа T, чтобы получитьновое значение типа T. Scalaz Semigroup идеально подходит для счета.

Следующие работы:

def matchList[T : Semigroup](ls: List[T]): List[T] = ls match {
  case 1 :: rest => rest
  case a :: b :: rest => (a |+| b) :: rest // |+| is a generic 'combining' operator
  case _ => ls
}
3 голосов
/ 23 декабря 2011

Я думаю, что проблема заключается в (a + b), единственное универсальное использование оператора + - это конкатенация строк, поэтому a и b должны оба быть Strings (или автоматически конвертируемыми в Strings) для того, чтобы быть действительным. Ваш параметризованный тип T не является строкой, поэтому он не компилируется.

2 голосов
/ 23 декабря 2011

Во втором примере ваши a, b переменные объявленного типа T не могут быть преобразованы в String, который является обязательным типом аргумента +, выведенным из вашей программы (то есть view применяется к типу аргументов + при отсутствии какой-либо другой информации).

В первом примере логический вывод может угадать правильную + функцию для применения, учитывая еепринимает в качестве аргументов тип элементов списка, и, к счастью, вы упомянули в объявлении типа, что тип этих элементов Int.Попробуйте набрать

"1"+2

1 + 2

... в REPL и посмотрите, что пытается сделать Scala.Затем прочитайте о views .

Теперь я предполагаю, что, используя указанный выше параметр типа T, вы пытаетесь написать функцию, которая работает с any numericтипа, не так ли?В этом случае вы можете работать с чертой Numeric.Я позволю вам прочитать о последствиях , прежде чем предложить следующее:

def matchList[T](ls: List[T])(implicit n:Numeric[T]): List[T] = {
  import n.mkNumericOps
  ls match {
    case 1 :: rest => rest
    case a :: b :: rest => (a + b) :: rest
    case _ => ls
}}

Вы получите:

matchList(List(1,2,3))
res2: List[Int] = List(2, 3)
matchList(List(2,3,4))
res4: List[Int] = List(5, 4)
matchList(List(2.0,3.0,4.0))
res5: List[Double] = List(5.0, 4.0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...