2016-08-17 10 views
3

のは、私は複数の種類のパラメータを取りDEFを持っているとしましょう:スカラでは、defの型パラメータを "カレー化"することは可能ですか?

def foo[A, B, C](b: B, c: C)(implicit ev: Writer[A])

しかし、意図した使用法はBCが推察すべきことであるが、型パラメータである(渡された引数に基づいて)。また、呼び出し側は実際にAを明示的に指定する必要があります(たとえば、コンパイラによって適切な暗黙的に選択されている)。残念ながら、Scalaでは、呼び出し元が指定する型パラメータのすべてまたはすべてを許可しません。ある意味で、私は型パラメータをカレーになりたい:Scalaでこれを実現するためにいくつかのトリックが

def foo[A][B, C]...

ありますか?

(私の具体的な例としては、完全な意味を成していない場合は、私が提案して、それを改善するために満足している。)

答えて

5

私はこれをやってのけることができました最良の方法は、保持しているクラスを定義することですカレットタイプの情報は、applyメソッドを使用して関数呼び出しをシミュレートします。

私はここにこれについて書いた - あなたの具体的な例についてhttp://caryrobbins.com/dev/scala-type-curry/

、あなたはfooのための署名にapplyないのための署名でimplicit ev: Writes[A]を配置する必要があると思います。暗黙の引数を明示的に渡すか暗黙的にapplyメソッドを呼び出すかのあいまいさが原因です。ここで

はあなたの例のための実装例だ -

object Example { 
    def foo[A]: _Foo[A] = _foo.asInstanceOf[_Foo[A]] 

    final class _Foo[A] private[Example] { 
    def apply[B, C](b: B, c: C)(implicit ev: Writes[A]): Unit = ??? 
    } 

    private lazy val _foo = new _Foo[Nothing] 
} 

あなたは、あなたがカレーを希望するとapplyメソッドに渡され、次の引数が推測されますあなたのタイプのパラメータを指定することができます。

Example.foo[Int]("bar", new Object) 

あなたは他のタイプのパラメータを指定する必要が終わる行う場合は、明示的applyを呼び出すことによってそれを行うことができます。しかし、私はまだこれを行う必要性を見たことがない。

Example.foo[Int].apply[String, Object]("bar", new Object) 

あなたはまた、私は前述の記事で議論構造型を、使用することができる中間型を使用したくない場合は、しかし、これにはreflectiveCallsと推論された型シグネチャが必要です。どちらも避けたいのです。

+1

非常によく書かれ、非常に巧妙です! – Alec

関連する問題