【问题标题】:Type polymorphic implicit class compile errors类型多态隐式类编译错误
【发布时间】:2014-08-12 19:24:05
【问题描述】:

我正在尝试创建一个通用构建器隐式类型类,用于基于生成器的测试,作为学习练习。下面的示例捕获了基本逻辑。 (而不是组合 FooLike 类型的成员,GenBuilder 将用于组合 scalacheck 的 Gen trait 的成员)

object Foo {
    trait FooLike[A] {
        def foo(a: A): String
    }

    object FooLike {
        implicit object FooLikeInt extends FooLike[Int] {
            override def foo(a: Int): String = a.toString
        }
    }

    implicit class GenBuilder[T](self: T)(implicit f: FooLike[T]){

        private var _items = Set(self)

        def |?|(that: GenBuilder[T]): GenBuilder[T] = {
            _items =  _items + that.self
            this
        }

        def items: Set[String] = _items.toSet.map((a: T) => f.foo(a))
    }

}

object Test {
    import Foo._
    import Foo.FooLike._
    def test = {
        val res = 11 |?| 12 |?| 13 |?| 14
        println(res.items)
    }
}


Test.test

导致以下编译错误:

/Users/pkinsky/genBuilder.scala:19: error: value self is not a member of Main.$anon.Foo.GenBuilder[T]
            _items =  _items + that.self

这些编译器错误让我很困惑:self 怎么可能不是 GenBuilder[T] 的成员?

(注意:我正在使用 'scala $filename' 作为脚本运行它,如果这对 Scala 的类型系统 voodoo 有任何影响)

【问题讨论】:

  • 如果把val self: T放在构造函数参数中会怎样?
  • 天哪,我是个白痴。只有案例类会自动公开没有 val 的构造函数参数。这不是深度类型系统的巫术,这是明显的打我的耳光。如果您想要功劳,请将此评论添加为答案:)

标签: scala types typeclass implicit


【解决方案1】:

这不是某些深层类型系统的巫术,而是Scala 中使用构造函数参数的不同方式。

将您的课程标题更改为

implicit class GenBuilder[T](val self: T)(implicit f: FooLike[T]){

(注意 val self)将使self 成为GenBuilder 的字段,而不仅仅是在构造函数/私有中可用。

案例类使用其所有参数自动执行此操作。

【讨论】:

    【解决方案2】:

    以下代码以某种方式有效。用that.getSelf 替换that.selfdef getSelf: T = self 会导致它编译和工作,按预期打印Set(11, 12, 13, 14)。即将推出:我的下一个问题,我在哪里问为什么?为什么会这样?

    object Foo {
        trait FooLike[A] {
            def foo(a: A): String
        }
    
        object FooLike {
            implicit object FooLikeInt extends FooLike[Int] {
                override def foo(a: Int): String = a.toString
            }
        }
    
        implicit class GenBuilder[T](self: T)(implicit f: FooLike[T]){
    
            private var _items = Set(self)
            def getSelf: T = self
    
            def |?|(that: GenBuilder[T]): GenBuilder[T] = {
                that.getSelf
                _items =  _items + that.getSelf
                this
            }
    
            def items: Set[String] = _items.toSet.map((a: T) => f.foo(a))
        }
    
    }
    
    object Test {
        import Foo._
        import Foo.FooLike._
        def test = {
            val res = 11 |?| 12 |?| 13 |?| 14
            println(res.items)
        }
    }
    
    
    Test.test
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-22
      相关资源
      最近更新 更多