13

当我想切换函数和对象时,我可以使用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在 trait中肯定存在从某个类混合的隐式转换SeqLike

4

2 回答 2

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

错误信息非常清楚。

虽然有从 to 的隐式转换StringSeqLike[_,_]但没有从(SeqLike[_, _]) => Intto的转换String => ?

这可以使用以下隐式转换来解决:

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

编辑 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)

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

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

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

只要有证据表明存在从to的隐式转换,它就允许|%>采用不直接在 a 上工作T但在 a上工作的函数。XTX

于 2011-01-15T17:01:17.107 回答
2

除非必要,否则不要使用存在类型。他们破坏了东西,这里不需要。

另一方面,看到另一个答案中的错误使事情变得更加清楚。当您使用|>. 如果你这样声明它是否有效:

def length2[CC <% SeqLike[_, _]](x: CC) = x.length * 2
于 2011-01-15T14:15:07.667 回答