This page is no longer maintained — Please continue to the home page at www.scala-lang.org

type checking problem

2 replies
Daniel Mahler
Joined: 2009-05-25,
User offline. Last seen 1 year 24 weeks ago.
in Scala-2.7.4 & current 2.80 snapshots I get the following:

scala> object Test {
     |
     |   trait ZZ {
     |     trait C1[T]{}
     |
     |     trait CF1[T, CT <: C1[T]]{}
     |
     |     trait A[T] {
     |       type R <: C1[T]
     |       type FR <: CF1[T, R]
     |       def fr : FR
     |     }
     |
     |     def f1[Y, AY <: A[Y]](y: Y, ay: AY) : AY#R
     |       = f2[Y, AY#R](y, ay.fr : AY#FR)
     |
     |     def f2[O, CO <: C1[O]](f: O, fr : CF1[O, CO]) : CO
     |   }
     | }
<console>:21: error: type mismatch;
 found   : AY#FR
 required: ZZ.this.CF1[Y,AY#R]
             = f2[Y, AY#R](y, ay.fr : AY#FR)
                                    ^

but I think AY#FR <: CF1[Y,AY#R] so why is this an error?

thanks
Daniel

Daniel Mahler
Joined: 2009-05-25,
User offline. Last seen 1 year 24 weeks ago.
Re: type checking problem


On Sun, Oct 11, 2009 at 11:58 PM, Daniel Mahler <dmahler@gmail.com> wrote:
in Scala-2.7.4 & current 2.80 snapshots I get the following:

scala> object Test {
     |
     |   trait ZZ {
     |     trait C1[T]{}
     |
     |     trait CF1[T, CT <: C1[T]]{}
     |
     |     trait A[T] {
     |       type R <: C1[T]
     |       type FR <: CF1[T, R]
     |       def fr : FR
     |     }
     |
     |     def f1[Y, AY <: A[Y]](y: Y, ay: AY) : AY#R
     |       = f2[Y, AY#R](y, ay.fr : AY#FR)
     |
     |     def f2[O, CO <: C1[O]](f: O, fr : CF1[O, CO]) : CO
     |   }
     | }
<console>:21: error: type mismatch;
 found   : AY#FR
 required: ZZ.this.CF1[Y,AY#R]
             = f2[Y, AY#R](y, ay.fr : AY#FR)
                                    ^

but I think AY#FR <: CF1[Y,AY#R] so why is this an error?

thanks
Daniel


I have found that I this code will compile if I make CF1 covariant in CT.

object Test {

  trait ZZ {
    type C1[T]

    type CF1[T, +CT <: C1[T]]

    trait A[T] {
      type R <: C1[T]
      type FR <: CF1[T, R]
      def fr : FR
    }

    def f1[Y, AY <: A[Y]](y: Y, ay: AY) : AY#R
       = f2[Y, AY#R](y, ay.fr)

    def f2[O, CO <: C1[O]](f: O, fr : CF1[O, CO]) : CO
  }
}

Unfortunately in my intended application CF1 is not covariant in CT
and I am havingtrouble figuring out what is forcing the covariance requirement.
Is there some other minor change that would make the above work?
The f2, C1 & CF1 reperesent fixed third party library interfaces;
though C1 & CF1 could be covariant in T.

I am trying to package up the fr, FR & R components
and provide a cleaner interface to f2 via f1
and ultimately make the ay parameter implicit
(the reason for trying to package things together in the first place)

If I remove the covariance and look at the -explaintypes output
there is one line that puzzles me:

experimental/users/mahler/java/porn/Tests.scala:19: error: type mismatch;
 found   : ay.FR
 required: ZZ.this.CF1[Y,AY#R]
       = f2[Y, AY#R](y, ay.fr)
                           ^
ay.FR < ZZ.this.CF1[Y,AY#R]?
  ay.FR < Nothing?
    <notype> < Nothing?
    false
    ZZ.this.CF1[Y,ay.R] < Nothing?
      <notype> < Nothing?
      false
      Any < Nothing?
        <notype> < Nothing?
        false
      false
    false
  false
  ZZ.this.CF1[Y,ay.R] < ZZ.this.CF1[Y,AY#R]?
    AY#R < ay.R?

*** Why does the ordering flip in the previous step?

      AY < ay.type?
        ZZ.this.A[Y] < ay.type?
        false
      false
      AY#R < Nothing?
        <notype> < Nothing?
        false
        ZZ.this.C1[Y] < Nothing?
          <notype> < Nothing?
          false
          Any < Nothing?
            <notype> < Nothing?
            false
          false
        false
      false
      ZZ.this.C1[Y] < ay.R?
        ZZ.this.C1[Y] < Nothing?
          <notype> < Nothing?
          false
          Any < Nothing?
            <notype> < Nothing?
            false
          false
        false
        Any < ay.R?
          Any < Nothing?
            <notype> < Nothing?
            false
          false
        false
      false
    false
    ZZ.this.CF1[Y,ay.R] < Nothing?
      <notype> < Nothing?
      false
      Any < Nothing?
        <notype> < Nothing?
        false
      false
    false
    Any < ZZ.this.CF1[Y,AY#R]?
      Any < Nothing?
        <notype> < Nothing?
        false
      false
    false
  false
false
[[syntax trees at end of typer]]// Scala source: Tests.scala
package <empty> {
  final object Test extends java.lang.Object with ScalaObject {
    def this(): object Test = {
      Test.super.this();
      ()
    };
    abstract trait ZZ extends java.lang.Object with ScalaObject {
      def /*ZZ*/$init$(): Unit = {
        ()
      };
      type C1[T >: Nothing <: Any]>: Nothing <: Any;
      type CF1[T >: Nothing <: Any, CT >: Nothing <: ZZ.this.C1[T]]>: Nothing <: Any;
      abstract trait A[T >: Nothing <: Any] extends scala.AnyRef {
        type R>: Nothing <: ZZ.this.C1[T];
        type FR>: Nothing <: ZZ.this.CF1[T,A.this.R];
        def fr: A.this.FR
      };
      def f1[Y >: Nothing <: Any, AY >: Nothing <: ZZ.this.A[Y]](y: Y, ay: AY): AY#R = ZZ.this.f2[Y, AY#R](y, ay.<error: method fr>);
      def f2[O >: Nothing <: Any, CO >: Nothing <: ZZ.this.C1[O]](f: O, fr: ZZ.this.CF1[O,CO]): CO
    }
  }
}

Thanks
Daniel
Daniel Mahler
Joined: 2009-05-25,
User offline. Last seen 1 year 24 weeks ago.
Re: type checking problem
I figured out my problem.
What I was actually after is:

object Test {

  trait ZZ {
    type C[O]
    type CF[O, CO <: C[O]]

    trait A[O, CO <: C[O]] {
      type CFO <: CF[O, CO]
      def cfo : CFO
    }

    def f1[O, CO <: C[O]](o: O, ao: A[O, CO]) : CO
       = f2[O, CO](o, ao.cfo)

    def f2[O, CO <: C[O]](o: O, cfo : CF[O, CO]) : CO
  }

Though, I suspect the benefit of these contortions is not apparent without the context :)

cheers
Daniel

On Mon, Oct 12, 2009 at 3:46 AM, Daniel Mahler <dmahler@gmail.com> wrote:


On Sun, Oct 11, 2009 at 11:58 PM, Daniel Mahler <dmahler@gmail.com> wrote:
in Scala-2.7.4 & current 2.80 snapshots I get the following:

scala> object Test {
     |
     |   trait ZZ {
     |     trait C1[T]{}
     |
     |     trait CF1[T, CT <: C1[T]]{}
     |
     |     trait A[T] {
     |       type R <: C1[T]
     |       type FR <: CF1[T, R]
     |       def fr : FR
     |     }
     |
     |     def f1[Y, AY <: A[Y]](y: Y, ay: AY) : AY#R
     |       = f2[Y, AY#R](y, ay.fr : AY#FR)
     |
     |     def f2[O, CO <: C1[O]](f: O, fr : CF1[O, CO]) : CO
     |   }
     | }
<console>:21: error: type mismatch;
 found   : AY#FR
 required: ZZ.this.CF1[Y,AY#R]
             = f2[Y, AY#R](y, ay.fr : AY#FR)
                                    ^

but I think AY#FR <: CF1[Y,AY#R] so why is this an error?

thanks
Daniel


I have found that I this code will compile if I make CF1 covariant in CT.

object Test {

  trait ZZ {
    type C1[T]

    type CF1[T, +CT <: C1[T]]

    trait A[T] {
      type R <: C1[T]
      type FR <: CF1[T, R]
      def fr : FR
    }

    def f1[Y, AY <: A[Y]](y: Y, ay: AY) : AY#R
       = f2[Y, AY#R](y, ay.fr)

    def f2[O, CO <: C1[O]](f: O, fr : CF1[O, CO]) : CO
  }
}

Unfortunately in my intended application CF1 is not covariant in CT
and I am havingtrouble figuring out what is forcing the covariance requirement.
Is there some other minor change that would make the above work?
The f2, C1 & CF1 reperesent fixed third party library interfaces;
though C1 & CF1 could be covariant in T.

I am trying to package up the fr, FR & R components
and provide a cleaner interface to f2 via f1
and ultimately make the ay parameter implicit
(the reason for trying to package things together in the first place)

If I remove the covariance and look at the -explaintypes output
there is one line that puzzles me:

experimental/users/mahler/java/porn/Tests.scala:19: error: type mismatch;
 found   : ay.FR
 required: ZZ.this.CF1[Y,AY#R]
       = f2[Y, AY#R](y, ay.fr)
                           ^
ay.FR < ZZ.this.CF1[Y,AY#R]?
  ay.FR < Nothing?
    <notype> < Nothing?
    false
    ZZ.this.CF1[Y,ay.R] < Nothing?
      <notype> < Nothing?
      false
      Any < Nothing?
        <notype> < Nothing?
        false
      false
    false
  false
  ZZ.this.CF1[Y,ay.R] < ZZ.this.CF1[Y,AY#R]?
    AY#R < ay.R?

*** Why does the ordering flip in the previous step?

      AY < ay.type?
        ZZ.this.A[Y] < ay.type?
        false
      false
      AY#R < Nothing?
        <notype> < Nothing?
        false
        ZZ.this.C1[Y] < Nothing?
          <notype> < Nothing?
          false
          Any < Nothing?
            <notype> < Nothing?
            false
          false
        false
      false
      ZZ.this.C1[Y] < ay.R?
        ZZ.this.C1[Y] < Nothing?
          <notype> < Nothing?
          false
          Any < Nothing?
            <notype> < Nothing?
            false
          false
        false
        Any < ay.R?
          Any < Nothing?
            <notype> < Nothing?
            false
          false
        false
      false
    false
    ZZ.this.CF1[Y,ay.R] < Nothing?
      <notype> < Nothing?
      false
      Any < Nothing?
        <notype> < Nothing?
        false
      false
    false
    Any < ZZ.this.CF1[Y,AY#R]?
      Any < Nothing?
        <notype> < Nothing?
        false
      false
    false
  false
false
[[syntax trees at end of typer]]// Scala source: Tests.scala
package <empty> {
  final object Test extends java.lang.Object with ScalaObject {
    def this(): object Test = {
      Test.super.this();
      ()
    };
    abstract trait ZZ extends java.lang.Object with ScalaObject {
      def /*ZZ*/$init$(): Unit = {
        ()
      };
      type C1[T >: Nothing <: Any]>: Nothing <: Any;
      type CF1[T >: Nothing <: Any, CT >: Nothing <: ZZ.this.C1[T]]>: Nothing <: Any;
      abstract trait A[T >: Nothing <: Any] extends scala.AnyRef {
        type R>: Nothing <: ZZ.this.C1[T];
        type FR>: Nothing <: ZZ.this.CF1[T,A.this.R];
        def fr: A.this.FR
      };
      def f1[Y >: Nothing <: Any, AY >: Nothing <: ZZ.this.A[Y]](y: Y, ay: AY): AY#R = ZZ.this.f2[Y, AY#R](y, ay.<error: method fr>);
      def f2[O >: Nothing <: Any, CO >: Nothing <: ZZ.this.C1[O]](f: O, fr: ZZ.this.CF1[O,CO]): CO
    }
  }
}

Thanks
Daniel

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland