2011-01-15 13 views
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から形質のある種の混合への暗黙の変換は間違いなく SeqLikeです。

+0

トリッキー。最初は、一度に1つしか暗黙的にすることはできないと思っていましたが、今はどこかに隠されている分散問題であるようです... – Debilski

+2

@Debilski、スカラズで '|>'がどこに定義されているのかわかりませんが私は自分自身を定義しようとしましたが、 "唯一の暗黙のルール"はそれが適用できないものだと思います。 "aoeu"は '|>'メソッドで暗黙的にクラスに変換し、次に 'SeqLike'に再度変換する必要があります。 – huynhjl

+1

エラーメッセージを表示します。誰もがScalazをすぐに利用できるわけではありませんが、通常、エラーメッセージは何がうまくいかないかを説明します。 –

答えて

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

エラーメッセージは非常に明確です。

StringからSeqLike[_,_]への暗黙の変換がありますが、(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への変換。

2

必要な場合を除き、存在しない型は使用しないでください。彼らは物事を壊し、ここでは必要ない。

一方、他の回答のエラーを見ると、明らかになっています。 |>を使用すると、2つの暗黙的な変換が求められます。あなたの代わりにこのようにそれを宣言した場合、それは動作します:

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

これは次を返します: 'タイプ(CC)=> scala.collection.SeqLike [_、_]'の証拠パラメータの暗黙の値を見つけることができませんでした – huynhjl

関連する問題