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