scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.85k stars 1.06k forks source link

LMS-inspired test cases for higher-kinded types #94

Closed namin closed 10 years ago

namin commented 10 years ago

This compiles without error:

import scala.language.higherKinds

trait Base {
  type Rep[T]
}

trait BaseExp extends Base {
  type Rep[T] = Exp[T]
  case class Exp[T](v: T)
}

The next trait compiles with an error (which feels inadequate and the source location is lost during reporting):

trait BaseStr extends Base {
  type Rep[T] = String
}
error: right-hand side of parameterized alias type must refer to a class
one error found

The next trait compiles with the same error (though I guess it is by design here and the source location is preserved):

trait BaseDirect extends Base {
  type Rep[T] = T
}
error: right-hand side of parameterized alias type must refer to a class
  type Rep[T] = T
             ^
one error found

All these traits compile fine with Scala 2.10.3.

namin commented 10 years ago

More higher-kinded type examples that compile with Scala 2.10.3, but not Dotty.

import scala.language.higherKinds

trait Test {
  trait Monad[X] {
    def x: X
  }
  sealed abstract class Either[A,B]
  case class Left[A,B](x: A) extends Either[A,B] with Monad[A]
  case class Right[A,B](x: B) extends Either[A,B] with Monad[B]
  def flatMap[X,Y,M[X]<:Monad[X]](m: M[X], f: X => M[Y]): M[Y] = f(m.x)
  println(flatMap(Left(1), {x: Int => Left(x)}))
}
error: type mismatch:
 found   : => _$hk$0(M[X]#x)
 required: X
  def flatMap[X,Y,M[X]<:Monad[X]](m: M[X], f: X => M[Y]): M[Y] = f(m.x)
                                                                     ^
error: type mismatch:
 found   : Test.this.Left[Nothing', Nothing']
 required: Nothing'{_$hk$0 = Nothing'}
  println(flatMap(Left(1), {x: Int => Left(x)}))
                      ^
error: type mismatch:
 found   : Test.this.Left[Nothing', Nothing']
 required: Nothing'{_$hk$0 = Y?}
  println(flatMap(Left(1), {x: Int => Left(x)}))
                                          ^
three errors found

Similar, with M not upper bounded and flatMap not implemented:

trait Test {
  trait Monad[X] {
    def x: X
  }
  sealed abstract class Either[A,B]
  case class Left[A,B](x: A) extends Either[A,B] with Monad[A]
  case class Right[A,B](x: B) extends Either[A,B] with Monad[B]
  def flatMap[X,Y,M[X]](m: M[X], f: X => M[Y]): M[Y]
  println(flatMap(Left(1), {x: Int => Left(x)}))
}
error: type mismatch:
 found   : Test.this.Left[Nothing', Nothing']
 required: Nothing'{_$hk$0 = Nothing'}
  println(flatMap(Left(1), {x: Int => Left(x)}))
                      ^
 found   : Test.this.Left[Nothing', Nothing']
 required: Nothing'{_$hk$0 = Y?}
  println(flatMap(Left(1), {x: Int => Left(x)}))
                                          ^
two errors found

This one actually works in Dotty with final val flagDeepSubTypeRecursions = false in Config (if true, the assertion in TypeComparer.monitoredSubtype fails.

trait Test {
  def flatMap[X,Y,M[X]](m: M[X], f: X => M[Y]): M[Y]
  println(flatMap(Some(1), {x: Int => Some(x)}))
}