In the following example, is there a way to avoid implicit permission choosing defaultInstance and using intInstance ? More background after code:
// the following part is an external fixed API trait TypeCls[A] { def foo: String } object TypeCls { def foo[A](implicit x: TypeCls[A]) = x.foo implicit def defaultInstance[A]: TypeCls[A] = new TypeCls[A] { def foo = "default" } implicit val intInstance: TypeCls[Int] = new TypeCls[Int] { def foo = "integer" } } trait FooM { type A def foo: String = implicitly[TypeCls[A]].foo } // end of external fixed API class FooP[A:TypeCls] { // with type params, we can use context bound def foo: String = implicitly[TypeCls[A]].foo } class MyFooP extends FooP[Int] class MyFooM extends FooM { type A = Int } object Main extends App { println(s"With type parameter: ${(new MyFooP).foo}") println(s"With type member: ${(new MyFooM).foo}") }
Actual output:
With type parameter: integer With type member: default
Required Conclusion:
With type parameter: integer With type member: integer
I am working with a third-party library that uses the above scheme to provide default instances for a class of type TypeCls . I think the above code is a minimal example demonstrating my problem.
It is assumed that users should mix with the FooM and instantiate the abstract element A The problem is that because of defaultInstance calling (new MyFooM).foo does not allow the specialized intInstance and instead makes defaultInstance , which is not what I want.
I added an alternative version using type parameters called FooP (P = Parameter, M = Member), which avoids defaultInstance by using context binding to the type parameter.
Is there an equivalent way to do this with type members?
EDIT: I have an error in my simplification, in fact foo not def , but val , so it is not possible to add an implicit parameter. Thus, no current answers are applicable.
trait FooM { type A val foo: String = implicitly[TypeCls[A]].foo }
source share