尝试为参数化的半身像创建通用零时使用Nothing bottom类型的问题 [英] Problems using Nothing bottom type while trying to create generic zeros for parametrized monoids

查看:101
本文介绍了尝试为参数化的半身像创建通用零时使用Nothing bottom类型的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的代码.它允许使用Casbah创建类型安全的MongoDB查询

trait TypesafeQuery[ObjectType, BuildType] {

  def build: BuildType

}

trait TypesafeMongoQuery[ObjectType] extends TypesafeQuery[ObjectType, DBObject]

case class TypesafeMongoQueryConjunction[ObjectType](queries: Seq[TypesafeMongoQuery[ObjectType]]) extends TypesafeMongoQuery[ObjectType] {
  override def build(): DBObject = $and(queries.map(_.build))
}

case class TypesafeMongoQueryDisjunction[ObjectType](queries: Seq[TypesafeMongoQuery[ObjectType]]) extends TypesafeMongoQuery[ObjectType] {
  override def build(): DBObject = $or(queries.map(_.build))
}

object TypesafeMongoQuery {

  // TODO could probably be reworked? see http://stackoverflow.com/questions/23917459/best-way-to-create-a-mongo-expression-that-never-matches
  val AlwaysMatchingQuery: DBObject = $()
  val NeverMatchingQuery: DBObject = $and($("_id" -> 1), $("_id" -> -1))

  def AlwaysMatchingTypesafeQuery[ObjectType] = new TypesafeMongoQuery[ObjectType] { override def build(): DBObject = AlwaysMatchingQuery }
  def NeverMatchingTypesafeQuery[ObjectType] = new TypesafeMongoQuery[ObjectType] { override def build(): DBObject = NeverMatchingQuery }

  def and[ObjectType](queries: TypesafeMongoQuery[ObjectType]*) = TypesafeMongoQueryConjunction(queries)
  def or[ObjectType](queries: TypesafeMongoQuery[ObjectType]*) = TypesafeMongoQueryDisjunction(queries)

  // TODO maybe define Scalaz Monoids

  def foldAnd[ObjectType](queries: Seq[TypesafeMongoQuery[ObjectType]]) = {
    queries.foldLeft(AlwaysMatchingTypesafeQuery[ObjectType]) { (currentQuery, queryInList) =>
      TypesafeMongoQuery.and(currentQuery, queryInList)
    }
  }
  def foldOr[ObjectType](base: TypesafeMongoQuery[ObjectType], queries: Seq[TypesafeMongoQuery[ObjectType]]) = {
    queries.foldLeft(NeverMatchingTypesafeQuery[ObjectType]) { (currentQuery, queryInList) =>
      TypesafeMongoQuery.or(currentQuery, queryInList)
    }
  }

}

工作正常,除非我对以下几行不满意:

  def AlwaysMatchingTypesafeQuery[ObjectType] = new TypesafeMongoQuery[ObjectType] { override def build(): DBObject = AlwaysMatchingQuery }
  def NeverMatchingTypesafeQuery[ObjectType] = new TypesafeMongoQuery[ObjectType] { override def build(): DBObject = NeverMatchingQuery }

我认为可能不会为每个折叠操作都创建这2个对象的新实例,而是使用类型为TypesafeMongoQuery[Nothing]的val/singleton,因为所构建的基础DBObject始终是相同的.

我已经尝试了一些方法,例如用[ObjectType,T <% ObjectType]替换我的签名,但都没有成功.

关于如何解决我的问题的任何想法?

解决方案

可以使ObjectType协变吗?

trait TypesafeQuery[+ObjectType, BuildType] {

  def build: BuildType

}

trait TypesafeMongoQuery[+ObjectType] extends TypesafeQuery[+ObjectType, DBObject]

object AlwaysMatchingTypesafeQuery extends TypesafeMongoQuery[Nothing] { override def build(): DBObject = AlwaysMatchingQuery }
object NeverMatchingTypesafeQuery extends TypesafeMongoQuery[Nothing] { override def build(): DBObject = NeverMatchingQuery }

Here's my code. It permits to create typesafe MongoDB queries using Casbah

trait TypesafeQuery[ObjectType, BuildType] {

  def build: BuildType

}

trait TypesafeMongoQuery[ObjectType] extends TypesafeQuery[ObjectType, DBObject]

case class TypesafeMongoQueryConjunction[ObjectType](queries: Seq[TypesafeMongoQuery[ObjectType]]) extends TypesafeMongoQuery[ObjectType] {
  override def build(): DBObject = $and(queries.map(_.build))
}

case class TypesafeMongoQueryDisjunction[ObjectType](queries: Seq[TypesafeMongoQuery[ObjectType]]) extends TypesafeMongoQuery[ObjectType] {
  override def build(): DBObject = $or(queries.map(_.build))
}

object TypesafeMongoQuery {

  // TODO could probably be reworked? see http://stackoverflow.com/questions/23917459/best-way-to-create-a-mongo-expression-that-never-matches
  val AlwaysMatchingQuery: DBObject = $()
  val NeverMatchingQuery: DBObject = $and($("_id" -> 1), $("_id" -> -1))

  def AlwaysMatchingTypesafeQuery[ObjectType] = new TypesafeMongoQuery[ObjectType] { override def build(): DBObject = AlwaysMatchingQuery }
  def NeverMatchingTypesafeQuery[ObjectType] = new TypesafeMongoQuery[ObjectType] { override def build(): DBObject = NeverMatchingQuery }

  def and[ObjectType](queries: TypesafeMongoQuery[ObjectType]*) = TypesafeMongoQueryConjunction(queries)
  def or[ObjectType](queries: TypesafeMongoQuery[ObjectType]*) = TypesafeMongoQueryDisjunction(queries)

  // TODO maybe define Scalaz Monoids

  def foldAnd[ObjectType](queries: Seq[TypesafeMongoQuery[ObjectType]]) = {
    queries.foldLeft(AlwaysMatchingTypesafeQuery[ObjectType]) { (currentQuery, queryInList) =>
      TypesafeMongoQuery.and(currentQuery, queryInList)
    }
  }
  def foldOr[ObjectType](base: TypesafeMongoQuery[ObjectType], queries: Seq[TypesafeMongoQuery[ObjectType]]) = {
    queries.foldLeft(NeverMatchingTypesafeQuery[ObjectType]) { (currentQuery, queryInList) =>
      TypesafeMongoQuery.or(currentQuery, queryInList)
    }
  }

}

It works fine, except I'm not satisfied with these lines:

  def AlwaysMatchingTypesafeQuery[ObjectType] = new TypesafeMongoQuery[ObjectType] { override def build(): DBObject = AlwaysMatchingQuery }
  def NeverMatchingTypesafeQuery[ObjectType] = new TypesafeMongoQuery[ObjectType] { override def build(): DBObject = NeverMatchingQuery }

I think It would be possible to not create a new instance of these 2 objects for each folding operation, but rather using a val / singleton of type TypesafeMongoQuery[Nothing] since the underlying DBObject being built would always be the same.

I've tried some things, like replacing my signatures everywhere by [ObjectType,T <% ObjectType] but with no great success.

Any idea on how to solve my problem?

解决方案

Can you make ObjectType covariant?

trait TypesafeQuery[+ObjectType, BuildType] {

  def build: BuildType

}

trait TypesafeMongoQuery[+ObjectType] extends TypesafeQuery[+ObjectType, DBObject]

object AlwaysMatchingTypesafeQuery extends TypesafeMongoQuery[Nothing] { override def build(): DBObject = AlwaysMatchingQuery }
object NeverMatchingTypesafeQuery extends TypesafeMongoQuery[Nothing] { override def build(): DBObject = NeverMatchingQuery }

这篇关于尝试为参数化的半身像创建通用零时使用Nothing bottom类型的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆