Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: using type parameters or abstract types as type bounds

Suppose I have:

class Bounded[A] {
  type apply[C <: A] = C
}

This compiles:

implicitly[Bounded[Any]#apply[String] =:= String]

This fails:

type Str = Bounded[Any]#apply[String]

...with:

[error] /home/grant/Workspace/scunits/test/src/main/scala/Box.scala:37: type arguments[String] do not conform to type apply's type parameter bounds [C <: A]
[error]   type Str = Bounded[Any]#apply[String]
[error]                           ^

I tried using abstract types instead of type parameters, with the same result. The only work-around I found was to instantiate the type. This compiles:

val boundedAny = new Bounded[Any]
type Str2 = boundedAny.apply[String]

Unfortunately I'm working with phantom types which don't have run time instances, often for performance reasons.

Why does Scala produce a compile error here? Is there a better work-around?

Thanks for any help.

Update: In addition to the workaround below, I needed a way to override types with abstract type bounds. I did this like so:

object Test {
  class AbstractBounded[A] {
    type apply[C <: A] <: A
    class Workaround[C <: A] {
      type go = apply[C]
    }
  }
  class Bounded[A] extends AbstractBounded[A] {
    type apply[C <: A] = C
  }

  type Str = Bounded[Any]#Workaround[String]#go
}
like image 444
Grant Avatar asked Oct 06 '14 19:10

Grant


1 Answers

How about:

scala> class Bounded[A] { class i[C <: A]{ type apply = C}}
defined class Bounded

scala> type TTT = Bounded[Any]#i[String]#apply
defined type alias TTT

scala> implicitly[TTT =:= String]
res4: =:=[TTT,String] = <function1>

Scala forgot to lookup generic (or another "abstract" type) before binding parameter to type alias. Given that =:= works fine - seems like a bug for me. Maybe implicits are resolving on another compilation level or just before this check.

like image 160
dk14 Avatar answered Sep 23 '22 09:09

dk14