It's kind of complicated to learn Scala's generic bounds. I know that:
T : Tr - T has type of Tr, meaning it implements a trait Tr
T <: SuperClass - T is subclass of SuperClass
T :> ChildClass - T is superclass of ChildClass
However, there are also many more operators:
<% and %>
=:=
<:< and >:>
<% and %>
<%< and >%>
I read about them, but as I said, there was was not comprehensible explanations. Could you make it clearer?
I've used a few type constraints:
The easiest are <: and >:. These are simple bounds on the type hierarchy.
trait A
trait B extends A
trait C extends B
then for a method
def doSomething[T >:C <:B](data:T)
either B or C can be substituted instead of T
Then type constraints that involves an addition of implicit parameter to the method.
def doSmth1[T: MyTypeInfo] (data:T)
is rewritten during compilation as
def doSmth1[T] (data:T)(implicit ev: MyTypeInfo[T])
whereas
def doSmth2[T <% SomeArbitratyType] (data:T)
is rewritten as
def doSmth2[T] (data:T)(implicit ev: T => SomeArbitratyType)
Both of the methods can be called if in the scope there is an instance that fits the implicit parameter. If there is no appropriate instance then compiler issues an error.
The view bound (<%) requires an implicit conversion that converts T to an instance of the other type (SomeArbitratyType).
More powerful is using "type classes". Inside the type class instance one may put many useful methods that can deal with the type T. In particular, one may put a conversion method and achieve similar result as view bounds.
Examples:
trait MyTypeInfo[T] {
def convertToString(data:T):String
}
def printlnAdv[T : MyTypeInfo](data:T) {
val ev = implicitly[MyTypeInfo[T]]
println(ev.convertToString(data))
}
somewhere in the scope there should be implicit value of type MyTypeInfo[T]:
implicit val doubleInfo = new MyTypeInfo[Double] {
def convertToString(data:Double):String = data.toString
}
or
implicit def convertToString(data:T):String
def printlnAdv[T <% String](data:T) {
val conversionResult = data : String
println(conversionResult)
}
somewhere in the scope there should be implicit function:
implicit def convertDoubleToString(data:Double):String = data.toString
The next weird symbols are =:= and <:<. These are used in methods that wish to ensure that a type has some property. Of course, if you declare a generic parameter then it is enough to have <: and >: to specify the type. However, what to do with types that are not generic parameters? For instance, the generic parameter of an enclosing class, or some type that is defined within another type. The symbols help here.
trait MyAlmostUniversalTrait[T] {
def mySpecialMethodJustForInts(data:T)(implicit ev:T =:= Int)
}
The trait can be used for any type T. But the method can be called only if the trait is instantiated for Int.
Similar use case exists for <:<. But here we have not "equals" constraint, but "less than" (like T<: T2).
trait MyAlmostUniversalTrait[T] {
def mySpecialMethod(data:T)(implicit ev:T <:< MyParentWithInterestingMethods)
}
Again the method can only can called for types that are descendants of MyParentWithInterestingMethods.
Then <%< is very similar to <%, however it is used the same way as <:< — as an implicit parameter when the type is not a generic parameter. It gives a conversion to T2:
trait MyAlmostUniversalTrait[T] {
def mySpecialMethod(data:T)(implicit ev:T <%< String) {
val s = data:String
...
}
}
IMHO <%< can safely be ignored. And one may simply declare the required conversion function:
trait MyAlmostUniversalTrait[T] {
def mySpecialMethod(data:T)(implicit ev:T => String) {
val s = data:String
...
}
}
Related
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.
I have a generic trait MappingPath, invariant regarding it's type parameters:
trait MappingPath[X<:AnyMapping, Y<:AnyMapping]
and an interface of a factory for it:
trait Pathfinder[X, Y] {
def apply(fun :X=>Y) :MappingPath[_<:AnyMapping,_<:AnyMapping]
def get(fun :X=>Y) :Option[MappingPath[_<:AnyMapping, _<:AnyMapping]]
}
I start a skeleton implementation which works for a single mapping:
class MappingPathfinder[M<:AnyMapping, X, Y] extends Pathfinder[X, Y] {
override def apply(fun :X=>Y) :MappingPath[M, _<:AnyMapping] = ???
override def get(fun :X=>Y) :Option[MappingPath[M, _<:AnyMapping]] = ???
}
which produces a compile error complaining that MappingPathfinder.apply overrides nothing and doesn't implement Pathfinder.apply. What's interesting, replacing M with _<:AnyMapping in apply's return type makes it compile, and no complaints are made regarding similar get method.
What's going on? I use scala 2.11.5.
EDIT:
I was able to circumvene my problem by adding explicit existantial annotations:
//Pathfinder
def apply(fun :X=>Y) :MappingPath[A, B] forSome { type A<:AnyMapping; type B<:AnyMapping }
//MappingPathfinder
def apply(fun :X=>Y) :MappingPath[A, B] forSome { type A>:M<:M; type B<:AnyMapping }
It seems to work, i.e
I can do:
(p :MappingPath[_<:AnyMapping, M]) ++ mappingPathfinder(f),
where ++ requires a path starting with the exact same type as this ends. It looks a bit silly and certainly confusing though.
Not an answer, but your use case can be simplified to:
trait Higher[U]
trait Super {
def foo: Higher[_]
}
trait Sub[M] {
override def foo: Higher[M] // error: method foo overrides nothing
}
Instead of existential types, I would use a type member:
trait Super {
type U
def foo: Higher[U]
}
trait Sub[M] {
type U = M
}
I think the difference is that in the case of the existential type, you only specify that the type parameter returned has some upper bound, but not necessarily that it is always the same type; whereas in my second example, type U means this will eventually be one specific type, and you can only refine a specific type. You can make upper bounds more precise:
trait Upper
trait A {
type U <: Upper
}
trait Specific extends Upper
trait B extends A {
type U <: Specific // type is "overridden"
}
If it's possible, I would avoid existential types, and your case seems a perfect fit for such avoidance. Most of the time, existential types are only needed for Java interop.
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.
I'm making a simple dependency injection framework, for constructor injection, in Scala. The idea is that objects that are DI'd put their required services in their constructor like regular parameters, and implement a typeclass that determines which of their arguments are taken from the container and which are passed by the user on instantiation.
So, it should look something like:
trait Container {
private singletons: Map[Class, AnyRef]
def getSingleton[T: Manifest] =
singletons(implicitly[Manifest[T]].erasure).asInstanceOf[T]
... methods for adding singletons, etc ...
}
class Foo(arg: String, svc: FooService) {
...
}
trait Constructor[T] { ??? }
object FooConstructor extends Constructor[Foo] {
def construct(arg: String)(implicit container: Container) =
new Foo(arg, container.getSingleton[FooService])
}
Now basically I'd like to be able to have a method called construct, which I can call as construct[Foo]("asd") and get a new instance of Foo with "asd" passed in to the constructor, and FooService gotten from the local container and passed in to the constructor. The idea is that it should grab the instance of the Constructor type class for Foo and in a typesafe way, know the number and types of arguments it should have. Also, and this is the hard part, I don't want to have to write out the types of the arguments - just the object to be constructed.
I've tried a couple things:
trait Constructor1[T, A] {
def construct(arg: A): T
}
trait Constructor2[T, A1, A2] {
def construct(arg1: A1, arg2: A2): T
}
def construct[T, A](arg1: A): T = implicitly[Constructor1[T, A]].construct(arg1)
...
This approach doesn't work though because it seems like in order to "summon" the Constructor type class instance, we need to write the types of the arguments, which is a lot of nasty boilerplate:
construct[Foo, String]("asd") // yuck!
Is there a way to use type classes (or anything else) to sort of partially infer the type parameters? We have the types of the constructor parameters for Foo defined in the Constructor instance definition, so if we can summon the instance we should be able to just call construct and get the right argument types. The issue is getting that instance without having to specify the constructor type arguments. I've played around with a bunch of different ideas for this, and I feel like with Scala's power and bag of tricks there just has to be a way I can write construct[Foo]("asd") and have the argument list be type safe. Any ideas?
UPDATE: Thanks to Miles Sabin's excellent answer + a slight modification, here's a method that only requires one type parameter and works for all different argument list lengths. This is a pretty simple way to painlessly wire up dependencies, without the cost of reflection:
trait Constructor1[T, A] { def construct(arg1: A)(implicit c: Container): T }
trait Constructor2[T, A, B] { def construct(arg1: A, arg2: B)(implicit c: Container): T }
implicit object FooConstructor extends Constructor1[Foo, String] {
def construct(arg1: String)(implicit c: Container) =
new Foo(arg1, c.getSingleton[FooService])
}
implicit object BarConstructor extends Constructor2[Bar, String, Int] {
def construct(arg1: String, arg2: Int)(implicit c: Container) =
new Bar(arg1, arg2, c.getSingleton[FooService])
}
class Construct[T] {
def apply[A](arg1: A)(implicit ctor: Constructor1[T, A], container: Container) =
ctor.construct(arg1)
def apply[A, B](arg1: A, arg2: B)(implicit ctor: Constructor2[T, A, B], container: Container) =
ctor.construct(arg1, arg2)
}
def construct[T] = new Construct[T]
construct[Foo]("asd")
construct[Bar]("asd", 123)
Type parameter inference in Scala is an all or nothing affair: if you explicitly supply any of the type arguments for a type parameter block then you must supply them all. Consequently, if you want to supply only some of a set of type arguments you must arrange for them to belong to separate type parameter blocks.
The way to do that in this case is to split the construct method into two stages: the first, which takes an explicit type argument and returns a function-like value; and a second, which applies the function-like value to the arguments for which you want the types to be inferred.
Here's how it might go,
// Function-like type
class Construct1[T] {
def apply[A](arg1: A)(implicit ctor : Constructor1[T, A]): T =
ctor.construct(arg1)
}
def construct[T] = new Construct1[T]
The result of invoking construct[Foo] is a value of type Construct1[Foo]. This has an apply method with a type parameter, which can be inferred, and an implicit parameter whose type is determined by both T and A. The invocation you want to make now looks like,
construct[Foo].apply("asd") // T explicit, A inferred as String
Scala's semantic sugaring rules around apply applies here which mean that this can be rewritten as,
construct[Foo]("asd")
which is exactly the result you want.
trait Construct[T, A] {
def apply(arg: A): T
}
class Constructor[T]{
def apply[A](arg : A)(implicit construct : Construct) = construct(arg)
}
object Constructor {
def apply[T] = new Constructor[T]
}
Constructor[T]("arg")
I want to relax the constraints on a trait's type parameter and instead impose them on a method in the form of an evidence parameter. Given some skeletal setup:
trait State[Repr]
object Observer {
def apply[Repr <: State[Repr]](reader: Reader[Repr]): Observer[Repr] =
new Observer[Repr] {}
}
trait Observer[A]
trait Reader [A]
This works:
trait StateX[Repr <: StateX[Repr]] extends State[Repr] {
protected def reader: Reader[Repr]
def observe: Observer[Repr] = Observer(reader)
}
And this doesn't:
trait StateY[Repr] extends State[Repr] {
protected def reader: Reader[Repr]
def observe(implicit ev: Repr <:< State[Repr]): Observer[Repr] = Observer(reader)
}
With message "inferred type arguments [Repr] do not conform to method apply's type parameter bounds [Repr <: State[Repr]]". Since the evidence ev suggests this conformation, I wonder how StateY can be fixed.
Your problem is that even though evidence of the form A <:< B implies that a value of type A can be converted to a value of type B it doesn't imply A <: B ... indeed, the main reason for using a type constraint or a view bound rather than an ordinary type bound is precisely because such a subtype relationship doesn't hold.
Consequently the constraint in StateY, Repr <:< State[Repr], isn't sufficient to satisfy the bound Repr <: State[Repr] on Observer's apply method. Given that you want to relax the constraint on StateX's type parameter your only option is to weaken the constraint on the apply method's type parameter correspondingly. That gets you something like the following using a view bound instead of an ordinary type bound,
object Observer {
def apply[Repr <% State[Repr]](reader : Reader[Repr]) : Observer[Repr] =
new Observer[Repr] {}
}
or alternatively,
object Observer {
def apply[Repr](reader : Reader[Repr])
(implicit ev : Repr <:< State[Repr]) : Observer[Repr] =
new Observer[Repr] {}
}
if you'd rather use constraints throughout.
The evidence suggests that a Repr can be converted to State[Repr]. It says nothing about what can be done with a Reader[Repr].
There is no general method (independant of T) to convert T[A] to T[B] given an A => B. That might be possible for a covariant T, but there is no such thing in the language.