Question

This is my first question here so hope I provide enough detail. Feel free to ask for clarification.

Taking the following into consideration, which works:

implicit def optionBsonReader[T, U](implicit ev: BsonReader[T, U]) = new BsonReader[Option[T], Option[U]] {
  def read(obj: Option[U]): Option[T] = {
    obj match {
      case Some(x) => Some(x.fromBson[T])
      case None => None
    }
  }
}

This piece of code converts Option wrapped pieces of BSON to another Option[T]. I thought that the same would work for lists but the following doesn't compile:

implicit def listBsonReader[T, DBObject](implicit ev: BsonReader[T, DBObject]) = new BsonReader[List[T], MongoCursor] {
  def read(cur: MongoCursor): List[T] = {
    cur.map(_.fromBson[T]).toList
  }
}

I am using the following code for the general mechanics:

package object bson {

  def bsonReader[A, B](implicit reader: BsonReader[A, B]) = reader
  def bsonWriter[A, B](implicit writer: BsonWriter[A, B]) = writer

  implicit def addWriter[A](any: A): WithWriter[A] = new WithWriter(any)
  implicit def addReader[A](any: A): WithReader[A] = new WithReader(any)
}

package bson {
  private[bson] class WithWriter[A](any: A) {
    def toBson[B](implicit writer: BsonWriter[A, B]): B = writer.write(any)
  }
  private [bson] class WithReader[B](any: B) {
    def fromBson[A](implicit reader: BsonReader[A, B]): A = reader.read(any)
  }
}

Compiler error: could not find implicit value for parameter reader: project.marshalling.bson.BsonReader[T,com.mongodb.casbah.Imports.DBObject] cur.map(_.fromBson[T]).toList

This strikes me as odd since it seems like the compiler is trying to evaluate T before fromBson has been called to supply a type. This strikes me as especially odd since the option reader seems to have no such complaints. I've only recently started to code in Scala in earnest so I am sure I am missing something here.

Please let me know if you need more info and hope you can help.

Best,

Dirk

Was it helpful?

Solution

In your listBsonReader, there is no reason for type U. Your cursor iterate on DBObject, map expects a DbObject => X function. I guess you have something like

implicit def withFromBson[U](x: U) = new {
   def fromBson[T](implicit ev : BsonReader[T,U]) : T = ...
}

In map, with _ typed DBObject, it is, quite normally looking from BsonReader[T, DBObject]. You provide none in implicit scope, only a BsonReader[T,U]. Just remove U and have your implicit parameter be BsonReader[T,DBObject].

The compiler is not trying to evaluate T in advance. It is trying to ensure that whatever T and U may be at call site, (in this case, U is the problem), it will have the implicit BSonReader[T, DBObject] it needs in implicit scope. I guess there is none in the general environment. You promise, with your implicit parameter, that you will give one BsonReader[T,U] at call site. That is not what it needs. Where the parameter not implicit (you would have to write the ev at when calling fromBson), you would have a similar error.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top