【问题标题】:Trouble getting scala type inference to work使 scala 类型推断无法正常工作
【发布时间】:2012-07-10 06:53:09
【问题描述】:

总体目标:

例如,假设我想开发一个非常可插拔的问题跟踪器。它的核心实现可能只支持票证 ID 和描述。其他扩展可能会添加对各种其他字段的支持,但这些字段可能存在于同一表的数据库中。即使没有,对数据库的查询数量也不应该随着扩展数量的增加而增加。他们应该能够为查询的定义做出贡献。

Item[A, B, R[_]] 表示一列,A 表示表类型(具有列表示形式),B 作为数据类型,R 作为类型构造函数,表示类型为 B 的列.所以R[B] 可能是 ScalaQuery 的NamedColumn[String],例如。

现在我正在尝试创建一个类型类来处理构建“查询”。

问题:

以 val q 开头的行(在末尾)应该简单地阅读 val q = query(items) 并且仍然可以编译。由于defaultNextB0 和/或B 推断为Nothing,各种尝试会产生推断类型参数不符合预期类型参数的错误,或“发散隐式扩展”错误,或其他错误。我认为隐式错误是由不正确的类型推断触发的。

我已经为此浪费了好几天(这是我的一个开源项目),所以如果有人能提供帮助,我真的很感激。

  class CanBuildQuery[A, B, R[_], Q, I <: Item[A, B, R]](val apply: I => A => Q)

  trait Low {
    implicit def defaultNext[A, B, R[_], B0, P <: Item[A, B0, R], I <: NextItem[A, B, B0, R, P], PQ](
      implicit cbq: CanBuildQuery[A, B0, R, PQ, P]
    ): CanBuildQuery[A, B, R, (PQ, R[B]), I] =
      new CanBuildQuery[A, B, R, (PQ, R[B]), I](sys.error("todo"))
  }

  object CanBuildQuery extends Low {
    implicit def defaultFirst[A, B, R[_]]:
      CanBuildQuery[A, B, R, R[B], FirstItem[A, B, R]] =
        new CanBuildQuery[A, B, R, R[B], FirstItem[A, B, R]](_.get)
  }

  def query[A, B, R[_], Q, I <: Item[A, B, R]](
    i: I with Item[A, B, R]
  )(
    implicit cbq: CanBuildQuery[A, B, R, Q, I]
  ): A => Q =
    cbq apply i

  trait Item[A, B, +R[_]] {    
    def get: A => R[B]
  }    
  trait FirstItem[A, B, +R[_]] extends Item[A, B, R] {    
    def get: A => R[B]
  }    
  trait NextItem[A, B, B0, +R[_], I <: Item[A, B0, R]] extends Item[A, B, R] {   
    val prev: I
    def get: A => R[B]
  }

  val items =
    new NextItem[Boolean, String, Long, Option, FirstItem[Boolean, Long, Option]]{
      val get = { _:Boolean => "hello" }
      val prev = new FirstItem[Boolean, Long, Option] {
        val get = { _:Boolean => 73 }
      }
    }

  val q = query(items)(CanBuildQuery.defaultNext(CanBuildQuery.defaultFirst))

【问题讨论】:

  • 你真的希望有人阅读和分析这一切吗?你必须缩小范围。请尊重读者的时间
  • 顺便说一句,我认为 SO 帮助应该是针对特定问题,而不是像“我不能自己开发系统的这一部分,所以我请其他人来构建它”。
  • 我认为反对票完全没有。很可能,它们来自对问题不了解的人,只是看着一堆代码并认为“哎呀,这很难!”。问题已明确说明,虽然我更喜欢较低的 LoC,但我碰巧知道这已经是较低的 LoC。
  • 由于括号、方括号和函数中的参数数量,代码无法编译。你能解决这些问题以帮助处理如此大量的代码吗?
  • @ChrisJamesC - 看起来其他人编辑了代码并且不小心遗漏了一个]。我修好了。

标签: scala implicits


【解决方案1】:

在 G-d 的帮助下,包括来自 Josh Seureth 的一些见解和建议,我得到了它的工作:

  trait Item[A] {
    type B
    type R[_]
    def get: A => R[B]
  }
  object Item {
    def apply[A, B, R[_]](get: A => R[B])(render: B => String => String) = {
      val get0 = get
      type B0 = B
      type R0[T] = R[T]
      new FirstItem[A] {
        type B = B0
        type R[T] = R0[T]
        def get = get0
      }
    }
  }
  trait FirstItem[A] extends Item[A] {
    type B
    def get: A => R[B]
    def &(item: Item[A]) =
      new NextItem[A] {
        type P = FirstItem.this.type
        type B = item.B
        type R[T] = item.R[T]
        val prev = FirstItem.this: FirstItem.this.type
        def get = item.get
      }
  }
  trait NextItem[A] extends Item[A] {
    type B
    type P <: Item[A]
    type _P = P
    val prev: P
    def get: A => R[B]
    def &(item: Item[A]) =
      new NextItem[A] {
        type P = NextItem.this.type
        type B = item.B
        type R[T] = item.R[T]
        val prev = NextItem.this: NextItem.this.type
        def get = item.get
      }
  }

  class CanBuildQuery[A, +Q, -I](val apply: I => A => Q)
  class CanBuildQueryImplicits {
    def apply[A, ]
    implicit def defaultNext[A, I <: NextItem[A], PQ](implicit cbq: CanBuildQuery[A, PQ, I#P]): CanBuildQuery[A, (PQ, I#R[I#B]), I] =
      new CanBuildQuery[A, (PQ, I#R[I#B]), I](ni => a => query(ni.prev)(cbq)(a) -> ni.get(a).asInstanceOf[I#R[I#B]])
    implicit def defaultFirst[A, B, I <: FirstItem[A]]: CanBuildQuery[A, I#R[I#B], I] =
      new CanBuildQuery[A, I#R[I#B], I](i => i.get.asInstanceOf[A => I#R[I#B]])
  }
  def query[A, Q, I <: Item[A]](i: I with Item[A])(implicit cbq: CanBuildQuery[A, Q, I]): A => Q = cbq apply i
}

  val items =
    Item((_: Field.type).id)(x => _ + " " + x) &
      Item((_: Field.type).name)(x => _ + " " + x) &
      Item((_: Field.type).allowMultiple)(x => _ + " " + x)

   val q = query(items) apply Field
   println(q)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2011-10-16
    • 2014-12-27
    • 2019-07-18
    • 1970-01-01
    • 2013-11-20
    • 1970-01-01
    相关资源
    最近更新 更多