在Scala中,可能会“咖喱" def的类型参数? [英] In Scala, is it possible to "curry" type parameters of a def?

查看:89
本文介绍了在Scala中,可能会“咖喱" def的类型参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个使用多个类型参数的def:

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])

但是,预期用途是应该推断类型参数BC(基于传入的参数).并且调用方只需要真正地显式指定A(例如,由编译器选择适当的隐式).不幸的是,Scala仅允许调用者指定全部或不指定任何类型参数.从某种意义上说,我希望使用类型参数:

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]...

在Scala中是否有一些技巧可以做到这一点?

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.)

推荐答案

我能够做到这一点的最好方法是定义一个保存咖喱类型信息的类,然后使用apply方法来模拟函数调用.

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.

我在这里写过- http://caryrobbins.com/dev/scala -type-curry/

对于您的特定示例,您需要将implicit ev: Writes[A]放在apply的签名中,而将 not 放在foo的签名中.这是因为它导致在显式传递隐式参数或隐式调用apply方法之间产生歧义.

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]
}

然后您可以提供您希望使用的类型参数,然后将推断出传递给apply方法的以下参数.

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)

如果确实需要指定其他类型参数,则可以通过显式调用apply来实现.但是,我从未见过需要这样做.

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)

如果您不想使用中间类型,也可以使用结构类型,我在前面的文章中已经讨论过;但是,这需要reflectiveCalls和推断的类型签名,我都希望避免这两种情况.

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.

这篇关于在Scala中,可能会“咖喱" def的类型参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆