Preventing accidental argument type information loss


Assume I have a library that exposes the following Foo and FooT:

trait Foo {type T}
trait FooT[T0] extends Foo {type T = T0}

The library user can use an argument of type Foo in several ways:

val ft = new FooT[Int]{}
def foo1[T](f : FooT[T]) = f
def foo2[F <: Foo](f : F) = f
def bad_foo(f : Foo) = f

Calling foo1(ft) or foo2(ft) will preserve the knowledge that T is Int, but calling bad_foo will not.
Is there some way I can warn the library user in cases similar to bad_foo?


Why not just specify the return type?

def good_foo(f : Foo): Foo { type T = f.T } = f


I don’t think the OP wants to return the Foo. That bad_foo, if I understood correctly, will be defined by the library user. Issue is, how do we enforce the user to retain the T in Foo[T].

Wondering if implicits are of potential use here.


Exactly. Loosing T is a mistake on behalf of the user.


If it’s important to preserve, use a type parameter instead of a type member. Type member syntax makes it easy to leave off and hard to preserve. Type parameter syntax makes it easier to preserve, and harder to leave off.


Yes, of course. But I need to expose both to the user, to have the possibility to use Foo just in an upper-bound position.