编译器不解析默认类型函数参数

时间:2017-07-03 15:21:41

标签: scala function types functional-programming

我有一个函数,它将一个类型化的排序函数作为参数,我希望这个sort函数有一个默认参数:

def foo[T](sort: MyObject => T = _.position)(implicit o: Ordering[T])

MyObject.position会返回Int

可以理解,我收到了这个错误:

Expression of type (MyObject) => Int doesn't conform to expected type (MyObject) => T

好的,但是我希望编译器能够确定在默认情况下TInt并检查Ordering[Int]范围内implicit是否可用。

如何帮助编译器解决此问题?

1 个答案:

答案 0 :(得分:2)

您可以使用带有和不带参数的重载函数:

def foo(): FooResult = foo(_.position)
def foo[T](sort: MyObject => T)(implicit o: Ordering[T]): FooResult = ???

我可以通过一种方式思考,如何使用非重载函数(以及一些样板)来实现它。

您可以使用一个特殊参数,它包含sort函数,foo的排序甚至实现,并提供从适当函数到此参数的隐式转换。这基本上是Magnet pattern的应用。

sealed trait Magnet {
  type T

  val sort: MyObject => T
  implicit val o: Ordering[T] 

  def fooImpl = ???
}

object Magnet {
  implicit def fromSort[T0](sortArg: MyObject => T0)(implicit ordArg: Ordering[T0]): Magnet = 
    new Magnet {
      type T = T0

      val sort = sortArg
      val o = ordArg
    }
}

def foo(sort: Magnet = (_: MyObject).position) = sort.fooImpl

一个缺点是,这会丢失参数的预期类型,因此您必须指定sort函数的参数类型。

您的案例的可用性值得怀疑,但它仍然是一个有趣的解决方案,并且可能在其他情况下有用。