Why does Scala type inference fail in one case but not the other? -


background: i'm using net.liftweb.record mongodb access database. @ point, in need of drawing table of collection of documents database (and render them ascii table). ran obscure type inference issues easy solve nevertheless made me want understand why happening.

reproduction: simplicity, i've reduced code (what think is) absolute minimum, depends on net.liftweb.record , none of mongo specific types. i've kept real-life body of function under question make example more realistic.

maketable takes apples, , functions map apples columns. columns can either mapped real field on apples, or dynamically computed value (with name). able mix 2 (real fields , dynamic values) in single seq, defined structural type col.

to see how code (below) behaves, try following variants of cols parameter maketable:

// ok: cols = seq(_.isdone) cols = seq(job => dyncol1) cols = seq(job => dyncol1, job => dyncol2)  // error: found: seq[job => object], required: seq[job => test.col] cols = seq(_.isdone, job => dyncol1) cols = seq(_.isdone, job => dyncol2) cols = seq(_.isdone, job => dyncol1, job => dyncol2) 

...so whenever _.isdone (i.e. column maps physical field) mixed other "flavor" of column, error occurs (case 1). alone behaves well; other flavors of column behave when alone or mixed (case 2).

intuitive workaround: marking cols seq[job => col] fixes error.

counter-intuitive workaround: explicitly marking any of return values of functions in seq col, or of functions job => col, solves issue.


the code:

import net.liftweb.record.{ record, metarecord } import net.liftweb.record.field.intfield import scala.language.reflectivecalls  class job extends record[job] {   def meta = job   object isdone extends intfield(this) } object job extends job metarecord[job]  object test extends app {   type col = { def name: string; def get: }    def maketable[t](xs: seq[t])(cols: seq[t => col]) = {     assert(xs.size >= 1)     val rows = xs map { x => cols { map { _(x).get } }     val header = cols map { _(xs.head).name }     (header +: rows)   }    val dyncol1 = new { def name = "dyncol1"; def = "dyn1" }   val dyncol2 = new { def name = "dyncol2"; def = "dyn2" }    val jobs = seq(job.createrecord, job.createrecord)   maketable(jobs)(seq(     _.isdone,     job => dyncol1,     job => dyncol2   )) } 

p.s. i'm not adding lift or lift-record tag because think not related lift , scala question triggered happens lift-specific situation. feel free correct me if i'm wrong.


Comments

Popular posts from this blog

python - Subclassed QStyledItemDelegate ignores Stylesheet -

java - HttpClient 3.1 Connection pooling vs HttpClient 4.3.2 -

SQL: Divide the sum of values in one table with the count of rows in another -