用scalaz'|>切换函数和对象

cou*_*ech 13 scala scalaz

scalaz |>想在切换功能和对象时使用操作符,这样可以获得更多的可读性.我来介绍一个模型函数:

def length2(x:String) = x.length * 2
Run Code Online (Sandbox Code Playgroud) 现在,我可以用两种方式编写它:
"aoeu" |> length2
length2("aoeu")
Run Code Online (Sandbox Code Playgroud) 但是,如果我将此函数定义为更通用,它将停止工作.
def length2(x:SeqLike[_,_]) = x.length * 2
length2("aoeu") // ok
"aoeu" |> length2 // doesn't work
Run Code Online (Sandbox Code Playgroud) 为什么编译器不理解这个?肯定有一种隐含的转换,从String某种类混合到特质中SeqLike.

huy*_*hjl 12

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

错误消息非常清楚.

虽然从隐式转换StringSeqLike[_,_],没有从转换(SeqLike[_, _]) => IntString => ?.

这可以使用以下隐式转换来修复:

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

编辑2:这是一个非scalaz运算符.

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)
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

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

"abc" |%> l1
"abc" |%> l2
Run Code Online (Sandbox Code Playgroud)

它允许|%>采取不直接在工作的功能T,但在X只要有一个从隐式转换的证据TX.