Reputation: 75
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).
Upvotes: 0
Views: 199
Reputation: 22850
Since Logging
doesn't know which type constructor will be used for the Configuration
it has to carry over it like any other type parameter.
Thus:
trait Logging[F[_]] {
def config: Configuration[F]
// ...
}
The same will apply to whatever depends on Logging
it 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.
Upvotes: 2