J'ai un emplacement de trait que je ne veux pas changer. o code> peut être une chaîne code> ou
SEQ [String] CODE>
class Log[L <: Location](location: L)(implicit mapper: Mapper[L#O]) {
def getPath(date: String): L#O =
mapper.applyDate(location.value, date)
def getPath(dates: Seq[String]): Seq[String] =
mapper.applyDates(location.value, dates)
}
trait Mapper[A] {
def applyDate(path: A, date: String): A
def applyDates(path: A, dates: Seq[String]): Seq[String]
}
object Mapper {
def build(path: String, date: String): String = s"$path/$date"
implicit val stringMapper: Mapper[String] = new Mapper[String] {
override def applyDate(path: String, date: String): String = build(path, date)
override def applyDates(path: String, dates: Seq[String]): Seq[String] =
dates.map(build(path, _))
}
implicit val seqStringMapper: Mapper[Seq[String]] = new Mapper[Seq[String]] {
override def applyDate(path: Seq[String], date: String): Seq[String] =
path.map(build(_, date))
override def applyDates(path: Seq[String], dates: Seq[String]): Seq[String] =
path.flatMap(p => dates.map(build(p, _)))
}
}
3 Réponses :
Cela fonctionne pour moi: qui peut être utilisé comme vous le souhaitez. p> BTW, je vous recommanderais de rester à l'écart de Assurer une instance
Modifier h3>
sealed trait Log[L <: Location] {
protected type LL <: L
protected val l: LL
def getPath(date: String): l.O
def getPath(dates: List[String]): List[String]
}
object Log {
def apply[L <: Location](location: L)
(implicit mapper: Mapper[location.O]): Log[L] = new Log[L] {
override protected final type LL = location.type
override protected final val l: LL = location
override def getPath(date: String): l.O =
mapper.applyDate(l.value, date)
override def getPath(dates: List[String]): List[String] =
mapper.applyDates(l.value, dates)
}
}
Merci d'avoir souligné la question avec SEQ code>. 2 inconvénients avec votre proposition: il est possible d'instancier un journal qui n'a pas d'instances de mapper. L'emplacement est maintenant public (qui enfreint un peu l'encapsulation).
@Yannmoisan Voir la réponse modifiée, BTW Ceci obtient un complexe assez complexe car comme je vous l'ai dit auparavant, ce n'est pas clair quel est votre véritable objectif ultime. Par exemple, avez-vous vraiment besoin du type dépendant? Avez-vous vraiment besoin d'avoir le type précis l code>? Une solution de contournement simple serait simplement en utilisant le modèle AUX B> comme Dmytro suggéré.
Je ne vois aucune raison de ne pas utiliser simplement un paramètre de type ici.
class Log[O](location: Location[O])(implicit mapper: Mapper[O]) { def getPath(date: String): O = mapper.applyDate(location.value, date) } private val stringLog = new Log(new Location[String] { def value = "base" }) private val seqStringLog = new Log(new Location[Seq[String]] { def value = Seq("foo", "bar") })
Essayez de type raffiné
case class Log[_O](location: Location { type O = _O })(implicit mapper: Mapper[_O]) { def getPath(date: String): _O = mapper.applyDate(location.value, date) def getPath(dates: Seq[String]): Seq[String] = mapper.applyDates(location.value, dates) }
Pourquoi ne pas avoir
o code> comme paramètre de type?
Principalement pour éviter d'avoir 2 paramètres de type dans le journal:
Journal [O, L <: Emplacement [O]] code>. J'ai essayé tous les deux impliquer. Et je trouve un membre de type plus élégant dans ce cas.
Vous pouvez faire un journal [o] (emplacement: emplacement [O])
J'ai une réponse avec un paramètre de type que j'ai supprimé, mais change
emplacement code>. Je peux l'onduler si tu veux