Неявный параметр не найден в приложении функции - PullRequest
5 голосов
/ 22 февраля 2011

Если я определю функцию печати, которая принимает только числа как:

def print[T <% Number](value:T) {}
print: [T](value: T)(implicit evidence$1: (T) => java.lang.Number)Unit

Я могу позвонить по выше с:

print(5)
print(5.5)
print(6L) 

Но не со строкой:

print("aaa")  
<console>:7: error: could not find implicit value for evidence parameter of type (java.lang.String) => java.lang.Number
       print("aaa")

Это ожидается.

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

def print2[T <% Number]: T => Unit = value => { } 
print2: [T](implicit evidence$1: (T) => java.lang.Number)(T) => Unit

Обратите внимание, что неявный параметр является первым параметром вместо последнего.

Если я попытаюсь вручную определить вышеуказанную функцию:

def print3[T](implicit f: (T) => java.lang.Number)(value:T):Unit =  { }  
<console>:1: error: '=' expected but '(' found.
       def print3[T](implicit f: (T) => java.lang.Number)(value:T):Unit =  { }

По сути, приведенное выше не является допустимым определением функции, но компилятор создает его, когда я ранее определил print2.

Когда я вызываю print2 с Int:

print2(5)
<console>:7: error: type mismatch;
 found   : Int(5)
 required: (?) => java.lang.Number
       print2(5)

если я его параметризирую:

print2[Int](5)
<console>:7: error: type mismatch;
 found   : Int(5)
 required: (Int) => java.lang.Number
       print2[Int](5)

Похоже, он не может найти неявное преобразование из scala.Int => java.lang.Integer.

Как я могу переопределить печать так, чтобы она возвращала функции, а также правильно использовала импликации?

1 Ответ

5 голосов
/ 22 февраля 2011

Проблема здесь в том, что вы передаете 5 как неявный параметр.

Теперь, когда я на компьютере, есть несколько исправлений:

def print[T <% Number](value:T) {}

Вы называете это функцией , но это метод .

def print2[T <% Number]: T => Unit = value => { }

Опять же, вы называете это функцией.На самом деле, это метод , который возвращает функцию.Метод получает один параметр типа T и один неявный параметр.

print2(5)

Итак, здесь вы вызываете метод print2, передавая 5 в качестве его неявного параметра.Тип T еще не был выведен, потому что он сначала пытается согласовать 5 с ожидаемым типом T => Number.Тем не менее, поскольку 5 не соответствует Function1[T, Number], происходит сбой, даже не выводя T.

Существует множество способов вызова print2.Например:

print2(implicitly[Int => Number])
print2[Int]
(print2: Int => Unit)
val f: Int => Unit = print2

Однако, чтобы вызвать функцию, возвращаемую print2, вы должны избегать того, чтобы (5) выглядел как неявный параметр для метода print2.На самом деле есть только один приведенный выше случай, который требует чего-то другого:

print2(implicitly[Int => Number])(5)
print2[Int].apply(5)
(print2: Int => Unit)(5)
val f: Int => Unit = print2; f(5)

Теперь большинство этих примеров имеют явные, а не предполагаемые параметры типа.Давайте рассмотрим, что произойдет в его отсутствие:

print2.apply(5)

Поскольку ни один параметр не был передан в print2, он выбирает наиболее конкретный тип, который соответствует границам T.Поскольку T не имеет границ, выбирается Nothing.Затем он пытается найти неявное Nothing => Unit.Поскольку такого неявного не существует, происходит сбой.

Параметр функции, который будет возвращен print2, никогда не рассматривается для облегчения вывода типа.

...