Scala typeclass and implicit puzzle -
the last statement line below produces error: "type mismatch; found: testexpandablewithlibrary.this.library.type (with underlying type org.typeclass.library) required: v"
this trying implicit conversion. preceding line use typeclass function work fine.
any ideas on how fix it?
package org.typeclass /////////////////////////////////////////////////////////////////////////////// // 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]) /////////////////////////////////////////////////////////////////////////////// // 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) } } /////////////////////////////////////////////////////////////////////////////// // 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) // works val usem = root.expandwithm(library) // doesn't work! }
the problem need put second 2 type parameters on implicit class on extension method—as they'll inferred nothing
, since they're not referred in constructor arguments.
implicit class expandableitem[t](val template: t) extends anyval { def expandwithm[v, r](values: v)(implicit ev: expandable[t, v, r]): r = ev.expandwith(template, values) }
this should work fine.
Comments
Post a Comment