Reputation: 30320
I have a function that takes a typed sort function as a parameter, and I want this sort function to have a default parameter:
def foo[T](sort: MyObject => T = _.position)(implicit o: Ordering[T])
MyObject.position
returns an Int
.
Understandably, I am getting this error:
Expression of type (MyObject) => Int doesn't conform to expected type (MyObject) => T
OK, but I was hoping that the compiler would figure out that in the default case T
is Int
and check that an Ordering[Int]
is available in implicit
scope.
How can I help the compiler resolve this?
Upvotes: 1
Views: 33
Reputation: 14224
You can use an overloaded function with and without an argument:
def foo(): FooResult = foo(_.position)
def foo[T](sort: MyObject => T)(implicit o: Ordering[T]): FooResult = ???
I can think up one way though, how to actually do it with a non-overloaded function (and some boilerplate).
You can take a special argument, which packs the sort
function, the ordering and even the implementation of foo
, and provide an implicit conversion from a suitable function to this argument. This is basically an application of the 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
One drawback is that this loses the expected type for the argument, so you have to specify the type of the argument of the sort
function.
The usability for your case is questionable, but it's still an interesting solution nevertheless and may be useful in other situations.
Upvotes: 2