tks*_*sfz 5 scala currying type-parameter type-level-computation
假设我有一个带有多个类型参数的def:
def foo[A, B, C](b: B, c: C)(implicit ev: Writer[A])
但是,预期的用法是类型参数B,C应该推断(基于传入的参数).并且调用者应该只需要A明确指定(例如,具有由编译器选择的适当隐式).不幸的是,Scala只允许调用者指定所有类型参数或不允许任何类型参数.从某种意义上说,我希望咖喱的类型参数:
def foo[A][B, C]...
在Scala中有一些技巧可以实现吗?
(如果我的具体例子没有完全合理,我很乐意通过建议改进它.)
我能够解决这个问题的最好方法是定义一个包含curried类型信息的类,然后使用该apply方法模拟函数调用.
我在这里写过这篇文章 - http://caryrobbins.com/dev/scala-type-curry/
对于您的具体示例,您需要将implicit ev: Writes[A]签名放入签名apply而不是签名中foo.这是因为它在显式传递隐式参数或隐式调用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]
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以提供您希望咖喱的类型参数,并apply推断传递给方法的以下参数.
Example.foo[Int]("bar", new Object)
Run Code Online (Sandbox Code Playgroud)
如果您最终需要指定其他类型参数,则可以通过显式调用来执行此操作apply; 虽然,我从未见过有必要这样做.
Example.foo[Int].apply[String, Object]("bar", new Object)
Run Code Online (Sandbox Code Playgroud)
如果您不想使用中间类型,您也可以使用结构类型,我在上述帖子中讨论过; 但是,这需要reflectiveCalls和推断的类型签名,我都希望避免这两种签名.
| 归档时间: |
|
| 查看次数: |
706 次 |
| 最近记录: |