I think there is something I don't quite well understand when I have the following code:
trait Configuration[F[_]] {
def get(key: String): F[ConfigValue]
}
class InMemoryConfig extends Configuration[Option] {
override def get(key: String): Option[ConfigValue] = ???
}
class InFileConfig(path: String) extends Configuration[Try] {
override def get(key: String): Try[ConfigValue] = ???
}
trait Logging {
def config: Configuration[_] // does not work
// ...
}
class DefaultLogging {
override val config = new InMemoryConfig
// ...
}
The name of the classes are pretty much meaningless, the general goal is to have a member in the trait without defining the param type in order to delay the choice until the implementation (actually in the DefaultLogging class).
Since
Loggingdoesn't know which type constructor will be used for theConfigurationit has to carry over it like any other type parameter.Thus:
The same will apply to whatever depends on
Loggingit needs to specify the type or keep the dependency.Thus, a common observation would be if such direct dependency is needed or not, but that becomes a matter of design and sometimes personal preference.