Я пытаюсь расширить String
с помощью нового метода apply, который позволяет мне применять к нему функцию более высокого порядка. Пример:
case class A(s:String, f: List[String] => List[String])
val f: List[String] => List[String] = { ... stuff ... }
"foo"{f} // == A("foo", f)
Итак, я определил неявное преобразование из String во что-то с помощью метода apply, который принимает функцию List[String] => List[String]
.
implicit def c(s:String) = new {
def apply(f: List[String] => List[String]) = A(s, f)
}
Но когда я пытаюсь использовать его, преобразование сталкивается с тем, что в Predef, который преобразует String
в StringOps
.
scala> "foo"{f}
<console>:19: error: type mismatch;
found : java.lang.String
required: ?{val apply: ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method c in object $iw of type (s: String)java.lang.Object{def apply(f: (List[String]) => List[String]): A}
and method augmentString in object Predef of type (x: String)scala.collection.immutable.StringOps
are possible conversion functions from java.lang.String to ?{val apply: ?}
"foo"{f}
^
Почему он ищет универсальный метод применения (required: ?{val apply: ?}
), а не метод, который принимает аргумент моего типа (List[String] => List[String]
)?
Edit:
Я решил это, воздерживаясь от использования пустых строк для выражения переменных (в проекте я работаю над github ). Итак, теперь это выглядит так:
case class param(val v: String) {
def apply(f: Emit.Selector) = Variable(v, f)
}
val $foo = param("foo")
foo{selector} // works fine
И мне не нужно использовать импликации.
Дальнейшее обновление
Похоже, что при поиске scala ищет параметры типа в результирующих типах последствий. Я заставляю это работать, но сценарий с параметром функции и методом apply не работает. Как получилось?
scala> class A()
defined class A
scala> class B()
defined class B
scala> implicit def one(s:String) = new {
| def a(a:A) = s + " A"
| }
one: (s: String)java.lang.Object{def a(a: A): java.lang.String}
scala> implicit def another(s:String) = new {
| def a(b:B) = s + " B"
| }
another: (s: String)java.lang.Object{def a(b: B): java.lang.String}
scala> "hello" a new A
res1: java.lang.String = hello A
scala> "hello" a new B
res2: java.lang.String = hello B