问题
Let's suppose I have a def that takes multiple type parameters:
def foo[A, B, C](b: B, c: C)(implicit ev: Writer[A])
However, the intended usage is that type parameters B
and C
should be inferred (based on the passed-in arguments). And the caller should only need to really specify A
explicitly (e.g. to have an appropriate implicit chosen by the compiler). Unfortunately, Scala only allows all or none of the type parameters to be specified by the caller. In a sense, I want the type parameters to be curried:
def foo[A][B, C]...
Is there some trick to accomplish this in Scala?
(If my specific example doesn't make complete sense I'm happy to improve it with suggestions.)
回答1:
The best way I've been able to pull this off is by defining a class which holds the curried type information then uses the apply
method to simulate the function call.
I've written about this here - http://caryrobbins.com/dev/scala-type-curry/
For your specific example, you'd need to put the implicit ev: Writes[A]
in the signature for the apply
and not in the signature for foo
. This is because it causes ambiguity between explicitly passing the implicit argument or implicitly calling the apply
method.
Here's an example implementation for your example -
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]
}
You can then supply your type parameter you wish to curry and the following arguments passed to the apply
method will be inferred.
Example.foo[Int]("bar", new Object)
If you do end up needing to specify the other type parameters, you can do so by explicitly calling apply
; although, I've never seen a need to do this yet.
Example.foo[Int].apply[String, Object]("bar", new Object)
If you don't wish to use the intermediate type you can also use a structural type, which I discuss in the aforementioned post; however, this requires reflectiveCalls
and an inferred type signature, both of which I like to avoid.
来源:https://stackoverflow.com/questions/38988062/in-scala-is-it-possible-to-curry-type-parameters-of-a-def