Подтвердить что ты не робот

Функция переключения и объект со сказазом '|>

Я могу использовать оператор scalaz |>, когда я хочу переключать функцию и объект, чтобы можно было получить немного больше читаемости. Позвольте мне представить вам модельную функцию:

def length2(x:String) = x.length * 2
Теперь я могу записать ее в обоих направлениях:
"aoeu" |> length2
length2("aoeu")
Но если я определю эту функцию более общей, она перестанет работать.
def length2(x:SeqLike[_,_]) = x.length * 2
length2("aoeu") // ok
"aoeu" |> length2 // doesn't work
Почему компилятор этого не понимает? Существует определенно неявное преобразование из String в некоторый смешение класса в признаке SeqLike.
4b9b3361

Ответ 1

scala> "aoeu" |> length2
<console>:14: error: type mismatch;
 found   : (scala.collection.SeqLike[_, _]) => Int
 required: (java.lang.String) => ?
       "aoeu" |> length2

Сообщение об ошибке довольно ясно.

Несмотря на то, что существует неявное преобразование от String до SeqLike[_,_], переход от (SeqLike[_, _]) => Int в String => ? отсутствует.

Это можно исправить, используя следующее неявное преобразование:

implicit def liftFun[X, T <% X, U](f: (X) => U): (T) => U = {
  def g(t:T) = f(t)
  g _
}

Изменить 2: здесь находится немасштабированный оператор.

class Pipe[T](t:T) {
  def |%>[X, U](f: (X) => U)(implicit ev: T <%< X) = f(t)
}
implicit def toPipe[T](t:T) = new Pipe(t:T)

Затем вы можете использовать его следующим образом:

def l1(a:String) = a.length
def l2(a:Seq[_]) = a.length * 2

"abc" |%> l1
"abc" |%> l2

Он позволяет |%> принимать функцию, которая не работает непосредственно на T, а на X, пока есть доказательства неявного преобразования из T в X.

Ответ 2

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

С другой стороны, видя в ошибке в другом ответе, все стало более ясным. Вы запрашиваете два неявных преобразования, когда используете |>. Работает ли это, если вы так заявляете это:

def length2[CC <% SeqLike[_, _]](x: CC) = x.length * 2