Relationship between parameterized class with different type, Scala - scala

In Scala,
What is the relationship between parameterized class with different type?
For example,
class A[T]
What is the relationship between A[Int] (or A[String]) and A?
and what is the relationship between A[Int] and A[String] ?
I want to know, because I would like to do something like
case class A[T](v: T) { def print = println(v) }
def iter(s: Seq[A[???]]) = s.map(print) // What is the proper annotation of '???'
iter(Seq(A(1), A("Hello")) // 1 Hello

What is the relationship between A[Int] and A?
A is a type constructor of kind * → *, and A[Int] is one of the possible results of apply a type (Int) to the type constructor A.
What is the relationship between A[Int] and A[String]?
The least upper bound between these two types is A[_ >: String with Int], which can only be instantiated to A[Any] since it's the only super class of String and Int.
What is the proper annotation of '???'
In your example that would be Any, or a type parameter you could add to your def iter that would itself be instantiated to Any.

Types are related using Variance.
To answer your question, Java's wildcards equivalent in Scala is Existential types. So you can specify something like this:
def iter(s: Seq[A[_]]) = s.map(_.print)
which is equivalent to:
def iter(s: Seq[A[T] forSome {type T}]) = s.map(_.print)
You can also specify bounds like below:
def iter(s: Seq[A[_ <: CharSequence]]) = s.map(_.print)
println(iter(Seq(A[StringBuilder](new StringBuilder("Test")), A[String]("Hello"))))
[Explicit type specified in constructors to avoid implicit conversion to required type CharSequence].
Note that the following would not compile though:
def iter(s: Seq[A[CharSequence]]) = s.map(_.print)
println(iter(Seq(A[StringBuilder](new StringBuilder("Test")), A[String]("Hello"))))
This is where variance specification in class would help:
case class A[+T](v: T) {
def print = v
}
def iter(s: Seq[A[CharSequence]]) = s.map(_.print)
println(iter(Seq(A[StringBuilder](new StringBuilder("Test")), A[String]("Hello"))))

Related

Is it possible to put an upper type bound mandating that a class has a concrete definition of a member type?

Let's consider:
trait Abstract {
type T
def get :T
def set(t :T) :Unit
}
class Concrete[X](var x :X) extends Abstract {
override type T = X
override def get :T = x
override def set(t :T) = x = t
}
class Generic[M <: Abstract](val m :M) {
def get :M#T = m.get
def set(t :M#T) :Unit = m.set(t)
def like[N <: Abstract](n :N) :Generic[N] = new Generic(n)
def trans[N <: Abstract](n :N) :N#T = like[N](n).get
}
Class Generic rightfully won't compile here because M#T can be literally any type in existence and not m.T. This can be 'fixed' in two ways:
def set(t :m.T) :Unit = ???
or
class Generic[M <: Abstract with Singleton]
First is unfeasible because in practice Generic might not even have an instance of M to use its member type (which happens in my real-life case), and passing around path dependent types in a compatible way between classes and methods is next to impossible. Here's one of the examples why path-dependent types are too strong (and a huge nuissance):
val c = new Concrete[Int](0)
val g = new Generic[c.type](c)
c.set(g.get)
The last line in the above example does not compile, even though g :Generic[c.type] and thus get :c.type#T which simplifies to c.T.
The second is somewhat better, but it still requires that every class with a M <: Abstract type parameter has an instance of M at instantiation and capturing m.T as a type parameter and passing everywhere a type bound Abstract { type T = Captured } is still a huge pain.
I would like to put a type bound on T specifying that only subclasses of Abstract which have a concrete definition of T are valid, which would make m.T =:= M#T for every m :M and neatly solve everything. So far, I haven't seen any way to do so.
I tried putting a type bound:
class Generic[M <: Abstract { type T = O } forSome { type O }]
which seemingly solved the issue of set, but fails with trans:
def like[N <: Abstract { type T = O } forSome { type O }](n :N) :Generic[N] = ???
def trans[N <: Abstract { type T = O } forSome { type O}](n :N) :N#T = ???
which seems to me like a clear type system deficiency. Additionally, it actually makes the situation worse in some cases, because it defines T early as some O(in class Generic) and won't unify it when additional constraints become available:
def narrow[N <: M { type T = Int }](n :N) :M#T = n.get
The above method will compile as part of class Generic[M <: Abstract], but not Generic[M <: Abstract { type T = O } forSome { type O}]. Replacing Abstract { type T = O } forSome { type O } with Concrete[_] yields very similar results. Both of these classes could be fixed by introducing a type parameter for T:
class Generic[M <: Abstract { type T = O }, O]
class Generic[M <: Concrete[_]]
Unfortunately, in several places I rely on two-argument type constructors such as
trait To[-X <: Abstract, +Y <: Abstract]
and use the infix notation X To Y as part of my dsl, so changing them to multi-argument, standard generic classes is not an option.
Is there a trick to get around this problem, namely to narrow down legal type parameters of a class so that their member type (or type parameter, I don't care) are both expressible as types and compatible with each other?. Think of M as some kind of factory of values of T and of Generic as its input data. I would like to parameterize Generic in such a way, that its instances are dedicated to concrete implementation classes of M. Do I have to write a macro for it?
I'm not sure exactly why you're saying that using a path dependent type will be annoying here, so maybe my answer will be completely off, sorry about that.
What's the problem with this?
class Generic[M <: Abstract](val m: M) {
def get: M#T = m.get
def set(t: m.T): Unit = m.set(t)
}
object Generic {
def like[N <: Abstract](n: N): Generic[N] = new Generic(n)
def trans[N <: Abstract](n :N): N#T = like(n).get
}
class Foo
val f = new Generic(new Concrete(new Foo))
f.set(new Foo)
You're saying you won't always have an instance m: M, but can you provide a real example of exactly what you want to achieve?

How to avoid duplication of type constraint in scala

I encounter quite often the following issue in Scala :
Given a trait
trait Foo { def foo: String }
and a parameterized class
case class Bar[T <: Foo](t: T)
I'd like to write a method that work with a Bar without duplicating the type constraint, something like :
def doSth(bar: Bar[_]) = bar.t.foo
Unfortunately, it doesn't compile and I need to write :
def doSth[T <: Foo](bar: Bar[T]) = bar.t.foo
Why the compiler can't infer that if I have a Bar[_], the _ must be a Foo ?
Is there a workaround (abstract type will avoid the duplication, but it will add complexity to represent some constraints) ?
It seems as if
def doSth(bar: Bar[_]) = bar.t.foo
is essentially the same as
def doSth0(bar: Bar[X] forSome { type X }) = bar.t.foo
and type X is just completely unconstrained. In my opinion, the question should therefore be rather:
Why does the compiler allow something like Bar[X] forSome { type X } at all, even though X is not declared as subtype of Foo, whereas Bar requires the argument to be subtype of Foo?
I don't know an answer to that. Probably it again has something to do with java generics.
Workarounds
Given the trait and class
trait Foo { def foo: String }
case class Bar[T <: Foo](t: T)
the following two definitions work without an additional type parameter:
def doSth1(bar: Bar[X] forSome { type X <: Foo }) = bar.t.foo
def doSth2(bar: Bar[_ <: Foo]) = bar.t.foo
Another option would be to constrain the type of t in Bar itself:
case class Bar2[T <: Foo](t: T with Foo)
def doSth3(bar: Bar2[_]) = bar.t.foo

How to decompose a type constructor via implicits?

I have a class Foo that takes a type constructor F as type parameter:
case class Foo[F[_]](x: F[String])
Now I want to define a member method bar that is only applicable, if F[T] = Outer[Inner[T]] for some fixed outer type Outer, e.g. Option:
def bar[Inner[_]](implicit ev: ???): Foo[Inner]
The ??? must be something along a natural transformation F ~> Outer·Inner with · being composition of type constructors.
How does this implicit argument look like?
How can I get it from somewhere?
How to write type constructor composition?
Also how to best write composition of type constructors? I currently write using a type lambda ({type L[X] = Outer[Inner[X]]})#L.
Type equality for type constructors
I don't think there's one defined in ScalaZ, but it's fairly simple to make one, taking scalaz.Leibniz as a template. I won't focus on composition and convenience methods, and only get the substance:
sealed abstract class LeibnizK[F[_], G[_]] {
def subst[Z[_[_]]](p: Z[F]): Z[G]
}
object LeibnizK {
implicit def refl[F[_]] = new LeibnizK[F, F] {
override def subst[Z[_[_]]](p: Z[F]): Z[F] = p
}
}
Which seems to be the implicit you're looking for:
type Outer[A] = Option[A]
type Id[A] = A
case class Foo[F[_]](me: F[String]) {
// Oh boy, here comes type lambda
def bar[Inner[_]](implicit leibk: LeibnizK[
F,
({type L[A] = Outer[Inner[A]]})#L
]): Outer[Foo[Inner]] = leibk.subst(this).me.map(Foo(_)) // <- OK to use methods of Outer
}
assert(Foo[Option](Some("meh")).bar[Id] == Some(Foo[Id]("meh")))
ScalaFiddle
Better syntax for type composition
Check out kind projector compiler plugin. It allows you to write:
λ[A => Outer[Inner[A]]
// or
Lambda[A => Outer[Inner[A]]
instead of
({type L[A] = Outer[Inner[A]]})#L
And for simple cases (no nesting), there's even shorter syntax
(?, Int)
instead of
({type L[A] = (A, Int)})#L

Is it possible for Scala to infer types for Generic types passed into a dependent class?

Given the following:
trait A[X] {
def foo(): X
}
class B[T <: A[_]] {
def getFoo(a:T) = a.foo()
}
class C[T <: A[Z], Z] {
def getFoo(a:T):Z = a.foo()
}
Is it possible to make B work like C? Specifically getting the result type of a.foo().
scala> var b:B[A[Int]] = new B[A[Int]]()
scala> b.getFoo(AA(1))
res0: Any = 1
scala> var c:C[A[Int],Int] = new C[A[Int],Int]()
c: C[A[Int],Int] = C#4cc36c19
scala> c.getFoo(AA(1))
res1: Int = 1
b returns an Any, but c correctly returns an Int. This is obviously a contrived example, but it would greatly simplify by code if I could extract a subtype from a Generic type. Basically, knowing "Z" (as used in C) without having to pass it in explicitly - inferring from the type of A.
Obviously, C works as needed, but the issue is my framework is more akin to:
class D[T <: A[Z1], U <: B[Z2], Z1, Z2] extends E[T,U,Z1,Z2]
which then requires users of the framework to implement with 4 type parameters, when ideally it would only be 2
class D[T <: A[_], U <: B[_]] extends E[T,U]
Not a blocker, just an attempt at simplifying the exposed API.
You can do the following which is often used in certain typeclass based libraries:
trait Foo[H[_] <: Langh[_]]{
def thing[A](ha: H[A]): A = ha.ha()
}
This pushes the resolution of the type parameter to the invocation of the method thing. It uses higher-kinded types.
If fact, if you look at libs like ScalaZ, you'll see exactly this pattern:
trait Functor[F[_]]{
def map[A, B](fa: F[A])(f: A => B): F[B]
}
Reply to Comments
There is no way to have a type of U <: T[_] and then be able to extract out the type parameter of an actual T[A] because the very definition of it loses that information. If the above does not work for you, then I would suggest type classes:
trait Foo[U]{
def doStuff(u: U)(implicit ev: MyTypeClass[U]): ev.A = //...
}
wherein you only define your MyTypeClass implicits like the following:
trait Whatever[FA]{ /*...*/ }
object Whatever{
implicit def WhateverMTC[F[_] <: Bound[_], A0] = new MyTypeClass[F[A0]]{
type A = A0
//...
}
}
Then you can place your type bound on the implicit, your implicit carries with it the constraint that your type must be higher-kinded and you can get a method that returns the inner "hidden" type at the call site declaration.
That said, this is a lot of machinery when the first suggestion is much more elegant and a cleaner approach to the problem IMHO.

How can I write a function have a polymorphic return type based on the type argument of its type parameter?

I have some code like this:
sealed trait Foo[A] {
def value: A
}
case class StringFoo(value: String) extends Foo[String]
case class IntFoo(value: Int) extends Foo[Int]
I'd like to have a function which can use the A type given a subtype's type parameter.
// Hypothetical invocation
val i: Int = dostuff[IntFoo](param)
val s: String = dostuff[StringFoo](param)
I can't figure out how to declare dostuff in a way that works. The closest thing I can figure out is
def dostuff[B <: Foo[A]](p: Param): A
But that doesn't work because A is undefined in that position. I can do something like
def dostuff[A, B <: Foo[A]](p: Param): A
But then I have to invoke it like dostuff[String, StringFoo](param) which is pretty ugly.
It seems like the compiler should have all the information it needs to move A across to the return type, how can I make this work, either in standard scala or with a library. I'm on scala 2.10 currently if that impacts the answer. I'm open to a 2.11-only solution if it's possible there but impossible in 2.10
Another option is to use type members:
sealed trait Foo {
type Value
def value: Value
}
case class StringFoo(value: String) extends Foo { type Value = String }
case class IntFoo(value: Int) extends Foo { type Value = Int }
def dostuff[B <: Foo](p: Any): B#Value = ???
// Hypothetical invocation
val i: Int = dostuff[IntFoo](param)
val s: String = dostuff[StringFoo](param)
Note that both solutions mainly work around the syntactic restriction in Scala, that you cannot fix one type parameter of a list and have the compiler infer the other.
As you might know, if you have a parameter of type Foo[A], then you can make the method generic in just A:
def dostuff[A](p: Foo[A]): A = ???
Since that might not always be the case, we can try to use an implicit parameter that can express the relationship between A and B. Since we can't only apply some of the generic parameters to a method call (generic parameter inference is all or nothing), we have to split this into 2 calls. This is an option:
case class Stuff[B <: Foo[_]]() {
def get[A](p: Param)(implicit ev: B => Foo[A]): A = ???
}
You can check the types in the REPL:
:t Stuff[IntFoo].get(new Param) //Int
:t Stuff[StringFoo].get(new Param) //String
Another option along the same lines, but using an anonymous class, is:
def stuff[B <: Foo[_]] = new {
def apply[A](p: Param)(implicit ev: B <:< Foo[A]): A = ???
}
:t stuff[IntFoo](new Param) //Int
Here, I've used apply in stead of get, so you can apply the method more naturally. Also, as suggested in your comment, here I've used <:< in the evidence type. For those looking to learn more about this type of generalized type constraint, you can read more here.
You might also consider using abstract type members instead of generic parameters here. When struggling with generic type inference, this often provides an elegant solution. You can read more about abstract type members and their relationship to generics here.