переключить функцию и объект с помощью скаляза '|> - PullRequest
13 голосов
/ 15 января 2011

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

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

Ответы [ 2 ]

12 голосов
/ 15 января 2011
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 голосов
/ 15 января 2011

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

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

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