Неявное преобразование Scala для псевдонимов типов

Определять

type TA[T] = T => Int

implicit class TAOps[T](a: TA[T]) {
  def foo(): Unit = {println("TA")}
}

val ta: TA[Double] = x => x.toInt

Сейчас,

ta.foo()

не компилируется с сообщением value foo is not a member of ammonite.$sess.cmd1.TA[Double],

в то время как явный вызов

TAOps(ta).foo()

печатает TA. Почему неявное преобразование не работает в первом случае?


person Kamil Kloch    schedule 23.08.2017    source источник


Ответы (1)


Ваше неявное определение ожидает тип, который получает один параметр типа, то есть TA[T]

Ваше объявление: val ta: TA[Double] = ... является типом и не принимает никаких параметров типа. Таким образом, компилятор не будет использовать ваше неявное определение для проверки типа.

Вывод: у вас есть неявное преобразование типа для типа, который принимает параметр типа, а TA[Double] не принимает никаких параметров типа.

Решения:

1 — заменить неявное преобразование типа на получение Function1:

  implicit class TAOps[T](a: T => Int) {
    def foo: Unit = {
      println("TA")
    }
  }

2 - Используйте лямбда-выражения типа:

  implicit class TAOps[T](a: ({type Alias = TA[T]})#Alias) {
    def foo: Unit = {
      println("TA")
    }
  }

Здесь созданный вами тип каррируется. Таким образом, компилятор теперь будет применять эти неявные преобразования к соответствующим типам, он больше не ожидает тип, который получает 1 параметр типа.

Подробнее об лямбда-выражениях типов

person pedromss    schedule 23.08.2017
comment
Спасибо, @pedromss, все работает. Я не знал, что в этом сценарии играют роль «дыры» параметров типа. - person Kamil Kloch; 24.08.2017
comment
Я тоже узнал на собственном горьком опыте: P. Отвечает ли это на ваш вопрос? - person pedromss; 24.08.2017