我scalaz |>想在切换功能和对象时使用操作符,这样可以获得更多的可读性.我来介绍一个模型函数:
def length2(x:String) = x.length * 2Run 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 workRun 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)
错误消息非常清楚.
虽然从隐式转换String到SeqLike[_,_],没有从转换(SeqLike[_, _]) => Int到String => ?.
这可以使用以下隐式转换来修复:
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只要有一个从隐式转换的证据T来X.