Scala type parameter bounds - scala

I'm having some trouble understanding scala's type bounds system. What I'm trying to do is make a holder class that holds items of type T that can iterate over items of type A. What I have so far is:
class HasIterable[T <: Iterable[A], A](item:T){
def printAll = for(i<-item) println(i.toString)
}
val hello = new HasIterable("hello")
The class itself successfully compiles but attempting to create the hello value gives me this error:
<console>:11: error: inferred type arguments [java.lang.String,Nothing] do
not conform to class HasIterable's type parameter bounds [T <: Iterable[A],A]
val hello = new HasIterable("hello")
^
I would have expected hello to resolve as a HasIterable[String, Char] in that case. How is this problem solved?

String itself is not a subtype of Iterable[Char], but its pimp, WrappedString, is. In order to allow your definition to make use of implicit conversions, you need to use a view bound (<%) instead of an upper type bound (<:):
class HasIterable[T <% Iterable[A], A](item:T){
def printAll = for(i<-item) println(i.toString)
}
Now your example will work:
scala> val hello = new HasIterable("hello")
hello: HasIterable[java.lang.String,Char] = HasIterable#77f2fbff

Related

What is type and what is type constructor in scala

I'm a bit confused about understanding of what type in scala means.
In documents I read that List[Int] is a type and List is a type constructor.
but what keyword type means when I write the following?
val ls: scala.collection.immutable.List.type = scala.collection.immutable.List
And how this type related to type that can be defined as a field in a trait for example.
In a scala val assignment like the above:
val name: Tpe = expression
Tpe is the type of the identifier name. Hence:
val x: List.type = List
The type of the List object (aka List module or List companion) is List.type. This indicates that it is a singleton. All of this is completely orthogonal to the concept of a type constructor in type theory.
Type Constructors
In type theory, List (note: not the companion) is both a type (denoted *) and a type constructor (denoted * -> *) because when you supply a type argument to List (e.g. Int) then you have a type (i.e. List[Int]). Scala provides syntax for this construction. For example:
def foo[F[_]]: F[Int]
^^^^ ^^^
| + supply a type argument to F[_]
|
+ the type constructor F[_]
But you cannot really implement such a method unless you know more about F. For example, if there is a implicit scalaz.Monad[F], you might use the Monad.pure value to construct your F[Int] like so:
def foo[F[_]: Monad]: F[Int] = Monad[F].pure(1)
In Scala
Scala does let you pass around List as a type constructor as a type parameter to such a method. For example:
scala> def foo[F[_]]: F[Int] = ???
foo: [F[_]]=> F[Int]
scala> lazy val x = foo[List]
x: List[Int] = <lazy>
However the List you are supplying in foo[List] is not the companion
Note the declaration of foo will result in the following warning:
<console>:11: warning: higher-kinded type should be enabled
by making the implicit value scala.language.higherKinds visible.
This can be achieved by adding the import clause 'import
scala.language.higherKinds'
or by setting the compiler option -language:higherKinds.
See the Scaladoc for value scala.language.higherKinds for a discussion
why the feature should be explicitly enabled.
def foo[F[_]]: F[Int] = ???
^
what keyword type means when I write the following
type is a member defined on object in Scala.
Suppose you have a class and its companion object:
class Foo(a: String)
object Foo {
def apply(a: String) = new Foo(a)
}
Now suppose you want to write a method that accepts the object Foo as an input. What's its type?
If you write this:
def someMethod(fooObj: Foo) = fooObj.apply("x") // doesn't compile
it's not going to compile. Foo refers to the type of an instance of the class (i.e. the one returned by new Foo("x") or Foo("x")). That's why objects have a type member that can refer to their own type:
def someMethod(fooObj: Foo.type) = fooObj.apply("x") // compiles!
In your specific example List.type is the type of the companion object of List. Here's a couple of examples that I hope will clarify what it means:
val listObj: List.type = List
val anEmptyList: List[Int] = listObj.empty[Int] // List()
val aListOfIntegers: List[Int] = listObj.range(1, 4) // List[(1, 2, 3)
And how this type related to type that can be defined as a field in a trait for example.
The type keyword defines a type member. .type is a type member. Conceptually it's like every object in Scala has a type member named type, like this:
object Foo {
type type = Foo
}
Obviously this won't compile, but it gives you an idea of what it may look like.
In type-level programming you’d think of a List[+A] being a type constructor:
That is:
-List[+A] takes a type parameter (A),
-by itself it’s not a valid type, you need to fill in the A somehow - "construct the type",
-by filling it in with String you’d get List[String] which is a concrete type.
In Scala it is not valid to say something is of type List. Scala is more strict here, and won’t allow us to use just a List in the place of a type, as it’s expecting a real type - not a type constructor.
In brief:
List[+A] is a type constructor whereas List[String] is a real type.

Unable to resolve path dependent type class evidence w/o having value type accessible

I got stuck for like an hour to discover this fact:
class Foo {
trait TypeClass[X]
object TypeClass {
implicit val gimme = new TypeClass[Int]{}
}
def foo[X : TypeClass](p: X): Unit = println("yeah " + p)
}
// compiles
val foo = new Foo()
foo.foo(4)
//does not compile
new Foo().foo(4)
could not find implicit value for evidence parameter of type _1.TypeClass[Int]
[error] new Foo().foo(4)
[error]
I can't figure out why that is. The only thing that I can think of is that scalac doesn't find implicits within a Type that doesn't have a Value Type accessible on any prefix. It cannot be referenced. Scalac apparently needs to access that Foo.this.foo to resolve implicits in it, which it can't in this case.
I feel like that if you combine type classes and path dependent types, you are effectively doomed. You'll end up dealing with this kind of stuff. I did that because scalac wouldn't otherwise infer types in my API methods and user would have to declare them explicitly. So I chose this kind of design so that types are constructed in Foo[T] and api methods use the existing type, but I hit several really ugly problems and bugs of this kind that made my app look like an overengineered crap...
Path dependent types may be bound only to some stable immutable values, so the more obvious example also will not work, because immutability is not guaranteed:
scala> var foo = new Foo()
foo: Foo = Foo#4bc814ba
scala> foo.foo(4)
<console>:17: error: could not find implicit value for evidence parameter of type _37.TypeClass[Int]
foo.foo(4)
^
scala> def foo = new Foo()
foo: Foo
scala> foo.foo(4)
<console>:17: error: could not find implicit value for evidence parameter of type _39.TypeClass[Int]
foo.foo(4)
^
_37 means that type was not inferred. So, it seems like scala simply infer type only after it's assigned to some val. It's not related to implicits actually, this will give you the more clear explanation:
scala> class C {type K = Int}
defined class C
scala> var z = new C
z: C = C#4d151931
scala> def aaa(a: z.K) = a
<console>:16: error: stable identifier required, but z found.
def aaa(a: z.K) = a
^
scala> def z = new C
z: C
scala> def aaa(a: z.K) = a
<console>:16: error: stable identifier required, but z found.
def aaa(a: z.K) = a
^
Your new Foo expression is similar to def newFoo = new Foo, so there it's considered as unstable.

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
}
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.

Scala classOf for type parameter: how to call the function and how to restrict with upper type bounds

I'm working with JAX-RS in Scala and trying to parameterise a call to:
val jc = JAXBContext.newInstance(classOf[MyClassName])
I've been using ClassManifests as per the answer here but have a couple of things I'm still struggling with. As background, my JAX-RS representations all extend a stubbed Representation class:
class Representation {}
class ExampleRepresentation extends Representation { ... }
So far I've defined my function using a ClassManifest like so:
def get[R: ClassManifest](representation: R): String = {
val jc = JAXBContext.newInstance(classManifest[R].erasure)
...
}
My first question is a bit of a silly one: how do I call this function? I can't figure out what to pass in to get() for the R type and the representation value (the accepted answer to the original question doesn't make this clear). I tried implicit typing as per paradigmatic's comment but the below generates a compile error:
get(PlatformRepresentation)
Compiling main sources...
not found: value PlatformRepresentation
My second question is: is it possible to apply an upper type bound on the R object? In other words, I know that:
R <: Representation
Is there a way of bounding this in get()'s ClassManifest type declaration?
Many thanks!
You need to suppress the argument if you don't have any:
def get[R <: Representation: ClassManifest]: String = {
val classManifest = implicitly[ClassManifest[R]] //to retrieve the class manifest
}
To call it:
get[PlatformRepresentation]
The type gets between square brackets.
About your second question: yes, there is a way to do that:
def get[R <: Representation: ClassManifest](representation: R): String
When you declare type parameters, you may include one lower bound with >:, one upper bound with <:, and as many context bounds (with :) and view bounds (with <%) that you need.
an example:
scala> def b[T <: String : ClassManifest] (t:T) = t + " " + classManifest[T].era
sure;
b: [T <: String](t: T)(implicit evidence$1: ClassManifest[T])java.lang.String
scala> b("hello")
res2: java.lang.String = hello class java.lang.String
EDIT #paradigmatic is right, in your case it should be
scala> def c[T <: String : ClassManifest] = classManifest[T].erasure;
c: [T <: String](implicit evidence$1: ClassManifest[T])java.lang.Class[_]
scala> c[String];
res4: java.lang.Class[_] = class java.lang.String

How to use a wildcard for a higher-kinded type in Scala?

Let's say I have this trait
trait Ctx[C, V[_]]
I am unable to construct any method signature that takes a Ctx of which the second type parameter is unspecified (wildcard). E.g. this:
def test(c: Ctx[_, _]) = ()
doesn't compile ("error: _$2 takes no type parameters, expected: one"). Neither can I do
def test(c: Ctx[_, _[_]]) = ()
("error: _$2 does not take type parameters"). What am I missing?
I'm able to define this one:
def test[V[X]](c:Ctx[_,V]) {}
And it seems to work ok with type inference:
scala> trait Ctx[ C, V[ _ ]]
defined trait Ctx
scala> def test[V[X]](c:Ctx[_,V]) {}
test: [V[X]](c: Ctx[_, V])Unit
scala> class P extends Ctx[Int, List]
defined class P
scala> new P
res0: P = P#1f49969
scala> test(res0)
Edit: I suspect it won't be practical to replace Ctx to use an abstract type, but this is what I was able to do:
trait Ctx[C] { type V[X] }
class CtxOption[C] extends Ctx[C] { type V[X] = Option[X] }
class CtxList[C] extends Ctx[C] { type V[X] = List[X] }
def test(ctx:Ctx[_]) { println(ctx) }
val ctxOptInt = new CtxOption[Int]
val ctxListStr = new CtxList[String]
test(ctxOptInt)
test(ctxListStr)
val list = collection.mutable.ListBuffer[Ctx[_]]()
list += ctxOptInt
list += ctxListStr
list
Using an abstract type for V spares you the complicated (or impossible) task of figuring the type parameter syntax for a wildcard type constructor. Additionally as demonstrated in the ListBuffer example you can then handle objects where the V is a different type constructor (Option and List in my example). The first solution I provided would not allow you to do that.
Edit 2: How about?
trait AbstractCtx[C] { type W[X] }
trait Ctx[C,V[_]] extends AbstractCtx[C] { type W[X] = V[X] }
def test(ctx:AbstractCtx[_]) { println(ctx) }
You need to pass a type constructor for the second argument of Ctx. Scala is not able to infer the correct kind if you just pass _. Neither is it possible to define a type constructor with wildcards (i.e. _[_]] on the fly. Note that in your first example _$2 in the error message refers to the type passed as second argument to Ctx as a whole. In the second example however _$2 refers to the the first wildcard type in _[_]. See the location indicator in the error messages:
<console>:6: error: _$2 does not take type parameters
def test( c: Ctx[ _, _[ _ ]]) {}
^
The following works since here V is a type constructor of the right kind expected by Ctx.
def test[V[_]]( c: Ctx[ _, V]) {}