【问题标题】:Scala type mismatch when composing traits组成特征时的Scala类型不匹配
【发布时间】:2019-04-25 07:08:30
【问题描述】:

我正在尝试计算一些我以后需要参考的类型。

我试图通过将类型存储在类型成员中来实现这一点。

这是一个例子:

trait TypeClass[A] {
    def op(x: A): A
}

object TypeClass {

    implicit object FloatIsTypeClass extends TypeClass[Float] {
        override def op(x: Float) = x
    }

    implicit object DoubleIsTypeClass extends TypeClass[Double] {
        override def op(x: Double) = x
    }
}


object TraitBounds {

    trait Types1 {
        type Member1
        val cls1: TypeClass[Member1]
    }

    class Types1Impl[A](implicit ev: TypeClass[A]) extends Types1 {
        type Member1 = A
        override val cls1 = ev
    }

    trait Types2 {
        type Member2
        val cls2: TypeClass[Member2]
    }

    class Types2Impl[A](implicit ev: TypeClass[A]) extends Types2 {
        type Member2 = A
        override val cls2 = ev
    }

    trait AllTypes extends Types1 with Types2

    def mk(x: Int): AllTypes = {
        import TypeClass._

        val (instance1, instance2) =
            if (x == 1) {
                (new Types1Impl[Float](), new Types2Impl[Double]())
            } else {
                (new Types1Impl[Double](), new Types2Impl[Float]())
            }

        new AllTypes {
            override type Member1 = instance1.Member1
            override val cls1 = instance1.cls1
            override type Member2 = instance2.Member2
            override val cls2 = instance2.cls2
        }
    }

    def main(args: Array[String]): Unit = {
        val in = mk(1)
        println(in)
    }

}

我收到以下错误:

Error:(54, 43) type mismatch;
 found   : TypeClass[_1]
 required: TypeClass[this.Member1]
    (which expands to)  TypeClass[_1]
            override val cls1 = instance1.cls1

在我看来,我在表达一些应该可以接受的东西,但由于某种原因,编译器不理解我想要做什么(或者我错了)。

为什么会出现类型错误?有解决办法吗?

【问题讨论】:

    标签: scala generics types


    【解决方案1】:

    可能存在一些关于类型系统的错误,尤其是在这一行 val (instance1, instance2) =,因为在 if 的一个分支中,instance1 的类型是 Types1Impl[Float],而在另一个分支中是类型Types1Impl[Double],它可能被推断为类型Types1Impl[AnyVal],也许这就是导致问题的原因,但我对编译器了解不多,无法知道确切原因。

    但是,我对您的代码进行了一些重构,并使其对我有用。

    trait TypeClass[A] {
      def op(x: A): A
    }
    
    object TypeClass {
      implicit val FloatIsTypeClass: TypeClass[Float] = new TypeClass[Float] {
        override def op(x: Float): Float = x
      }
    
      implicit val DoubleIsTypeClass: TypeClass[Double] = new TypeClass[Double] {
        override def op(x: Double): Double = x
      }
    }
    
    object TraitBounds {
      trait Types1 {
        type Member1
        val cls1: TypeClass[Member1]
      }
    
      object Types1 {
        private class Types1Impl[A](implicit ev: TypeClass[A]) extends Types1 {
          override type Member1 = A
          override val cls1 = ev
        }
    
        def apply[A: TypeClass]: Types1 = new Types1Impl[A]
      }
    
      trait Types2 {
        type Member2
        val cls2: TypeClass[Member2]
      }
    
      object Types2 {
        private class Types2Impl[A](implicit ev: TypeClass[A]) extends Types2 {
          override type Member2 = A
          override val cls2 = ev
        }
    
        def apply[A: TypeClass]: Types2 = new Types2Impl[A]
      }
    
      trait AllTypes extends Types1 with Types2
      object AllTypes {
        def fromTypes(t1: Types1, t2: Types2): AllTypes = new AllTypes {
          override type Member1 = t1.Member1
          override val cls1 = t1.cls1
          override type Member2 = t2.Member2
          override val cls2 = t2.cls2
        }
      }
    
      def mk(x: Int): AllTypes =
        if (x == 1) {
          AllTypes.fromTypes(Types1[Float], Types2[Double])
        } else {
          AllTypes.fromTypes(Types1[Double], Types2[Float])
        }
    
      def main(args: Array[String]): Unit = {
        val in: AllTypes = mk(1)
        println(in)
      }
    }
    

    几个注意事项,总是更喜欢 implicit valsdefs 具有特定 类型签名 而不是 implicit objects,他们由于对象的类型为ThatObjectName.type,因此往往会弄乱类型系统。
    此外,将您的实现隐藏在工厂构造函数后面,以将它们的类型隐藏到父 trait

    【讨论】:

      猜你喜欢
      • 2016-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-02
      • 2016-10-13
      • 1970-01-01
      相关资源
      最近更新 更多