implicite La dernière ligne de déclaration produit ci-dessous une erreur: "incompatibilité de type Trouvée: TestExpandableWithLibrary.this.library.type (avec org.typeclass.Library de type sous-jacent) requis: V"Scala et de puzzle
Cette est où j'essaye de faire une conversion implicite. La ligne précédente où j'utilise simplement la fonction typeclass fonctionne bien.
Des idées pour y remédier?
package org.typeclass
///////////////////////////////////////////////////////////////////////////////
// the domain objects
case class Book(bookName: String)
case class Library(libraryName: String, books: Set[Book])
object Library {
def apply(libraryName: String, bookNames: String*): Library =
Library(libraryName, bookNames.map(Book(_)).toSet)
}
case class TreeClass(nodeName: String, children: Seq[TreeClass])
///////////////////////////////////////////////////////////////////////////////
// the typeclass definition
trait Expandable[T, V, R] {
def expandWith(template: T, values: V): R
}
object Expandable {
def expandWithF[T, V, R](template: T, values: V)(implicit ev: Expandable[T, V, R]): R =
ev.expandWith(template, values)
implicit class ExpandableItem[T, V, R](val template: T) extends AnyVal {
def expandWithM(values: V)(implicit ev: Expandable[T, V, R]): R =
ev.expandWith(template, values)
}
}
///////////////////////////////////////////////////////////////////////////////
// a typeclass implementation
object ExpandableImpls {
implicit object ExpandableTreeClass extends Expandable[TreeClass, Library, TreeClass] {
def expandWith(template: TreeClass, library: Library): TreeClass = {
val parentName = s"${template.nodeName}.${library.libraryName}"
val children = library.books.map(book => TreeClass(s"${parentName}.${book.bookName}", Seq.empty)).toSeq
TreeClass(parentName, children)
}
}
}
//@RunWith(classOf[JUnitRunner])
class TestExpandableWithLibrary /*extends FlatSpec*/ {
import Expandable._
import ExpandableImpls._
val library = Library("test", "black", "white")
val root = TreeClass("parent", Seq.empty)
val useF = expandWithF(root, library) // this works
val useM = root.expandWithM(library) // this doesn't work!
}
Parfait, merci beaucoup! – satyagraha
Pour ne pas être churlish, mais peut-être quelque part le long de la ligne idéalement le compilateur aurait pu me donner quelques indices quant à l'endroit où je vais à la dérive. Type d'inférence = Dragons Soyez ici! – satyagraha
@satyagraha: Je suis d'accord que l'erreur pourrait être mieux. C'est une bonne idée d'intérioriser la règle que si vous voulez un paramètre de type déduit, il devrait apparaître dans une position non générique dans les arguments, cependant. –