使用scalaz'|>切换功能和对象

时间:2011-01-15 13:16:38

标签: scala scalaz

当我想切换功能和对象时,我可以使用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
为什么编译器不理解这个?肯定是从_隐式转换为特质_中的某个类混合。

2 个答案:

答案 0 :(得分:12)

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

错误信息非常清楚。

虽然存在从StringSeqLike[_,_]的隐式转换,但无法从(SeqLike[_, _]) => Int转换为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

只要有|%>隐式转换的证据,{}允许T执行直接在X上工作但在T上不起作用的函数到X

答案 1 :(得分:2)

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

另一方面,看到其他答案中的错误使事情变得更加清晰。当您使用|>时,要求您进行两次隐式转换。如果你这样声明它是否有效:

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