I can use scalaz
|>
operator when I want to switch function and object so there can be a little more readability acquired. Let me introduce you a model function :
def length2(x:String) = x.length * 2
Now, I can write it in both ways:"aoeu" |> length2
length2("aoeu")
But if I define this function more generic, it stops working.def length2(x:SeqLike[_
,_
]) = x.length * 2
length2("aoeu") // ok
"aoeu" |> length2 // doesn't work
Why the compiler doesn't understand this? There is definitely an implicit conversion from String
to some class mixing in trait SeqLike
.
scala> "aoeu" |> length2
<console>:14: error: type mismatch;
found : (scala.collection.SeqLike[_, _]) => Int
required: (java.lang.String) => ?
"aoeu" |> length2
The error message is pretty clear.
Although there is an implicit conversion from String
to SeqLike[_,_]
, there is no conversion from (SeqLike[_, _]) => Int
to String => ?
.
This can be fixed using the following implicit conversion:
implicit def liftFun[X, T <% X, U](f: (X) => U): (T) => U = {
def g(t:T) = f(t)
g _
}
Edit 2: here is a non-scalaz operator.
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)
Then you can use it like this:
def l1(a:String) = a.length
def l2(a:Seq[_]) = a.length * 2
"abc" |%> l1
"abc" |%> l2
It allows |%>
to take a function that does not work directly on a T
but on a X
as long as there is evidence of an implicit conversion from T
to X
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With