I am integrating with some java api, that looks kinda like this (these are java classes, I'll just use scala syntax for brevity:
class AbstractFooBuilder[ActualType <: AbstractFooBuilder, WhatToBuild <: Foo] {
// ...
def withFoo(f: Foo): ActualType
def withBar(b: Bar): ActualType
// ...
def build: WhatToBuild
}
class FooBarBuilder extends AbstractFooBuilder[FooBarBuilder, FooBar]
class FooBazBuilder extends AbstractFooBuilder[FooBazBuilder, FooBaz]
// .. etc
There is a bunch of these, and I am trying to make the creation of these foos less repetitive with something like this:
def anyFoo[T <: Foo, B <: AbstractFooBuilder[B, T] : Manifest](foo: Foo, b: Bar) = manifest
.runtimeClass
.newInstance
.withFoo(foo)
.withBar(bar)
.build
The problem is, that now, to create FooBar, I have to write something like this:
val foobar = new anyFoo[FooBar, FooBarBuilder](foo, bar)
which is longer than I would like. Specifically, once FooBarBuilder type parameter is known, FooBaris the only possibility for the second param ... I wonder if there is some trick I am missing, that would make it possible to "infer" the other param, and only have to specify one.
Any ideas?
Unfortunately, the standard trick to split the type parameters doesn't work here because B depends on T.
But what about getting rid of Manifest and simplifying to
def anyFoo[T <: Foo](builder: AbstractFooBuilder[_, T])(foo: Foo, b: Bar) =
builder.withBar(b).withFoo(foo).build
? You call it as anyFoo(new FooBarBuilder)(foo, b), so T is inferred, solving your problem. And as a bonus, it's faster and there is no runtime error if your class happens not to have a default constructor.
If your method didn't always need to create the builder, you could use by-name parameter or () => AbstractFooBuilder[_, T].
EDIT: Given the comment, this could work:
def mkBuilder[B <: AbstractFooBuilder[B, _] : Manifest]: B = // the complex creation code
anyFoo(mkBuilder[FooBarBuilder])(foo, b) // infers FooBar
The question is whether you can implement mkBuilder without access to T, but if your original code doesn't need a Manifest[T], it should be possible.
Or even
implicit class AnyFoo[T, B <: AbstractFooBuilder[B, T]](builder: B) {
def apply(foo: Foo, b: Bar) = builder.withBar(b).withFoo(foo).build
}
mkBuilder[FooBarBuilder](foo, b)
If I'm reading code correctly. The code does not imply there is only one AbstractFooBuilder factory for this type and this is left to the caller to specify the factory to use.
If you can use implicit, you can do something like this
def anyFoo[T <: Foo](foo: Foo, b: Bar)(implicit factory: AbstractFooBuilder[T]): T = {
factory.
withBar(b).
withFoo(foo).
build
}
Related
Suppose you have a trait like this:
trait Foo[A]{
def foo: A
}
I want to create a function like this:
def getFoo[A <: Foo[_]](a: A) = a.foo
The Scala Compiler deduces Any for the return type of this function.
How can I reference the anonymous parameter _ in the signature (or body) of getFoo?
In other words, how can I un-anonymize the parameter?
I want to be able to use the function like
object ConcreteFoo extends Foo[String] {
override def foo: String = "hello"
}
val x : String = getFoo(ConcreteFoo)
which fails compilation for obvious reasons, because getFoo is implicitly declared as Any.
If this is not possible with Scala (2.12 for that matter), I'd be interested in the rational or the technical reason for this limitation.
I am sure there are articles and existing questions about this, but I appear to be lacking the correct search terms.
Update: The existing answer accurately answers my question as stated, but I suppose I wasn't accurate enough regarding my actual usecase. Sorry for the confusion. I want to be able to write
def getFoo[A <: Foo[_]] = (a: A) => a.foo
val f = getFoo[ConcreteFoo.type]
//In some other, unrelated place
val x = f(ConcreteFoo)
Because I don't have a parameter of type A, the compiler can't deduce the parameters R and A if I do
def getFoo[R, A <: Foo[R]]: (A => R) = (a: A) => a.foo
like suggested. I would like to avoid manually having to supply the type parameter R (String in this case), because it feels redundant.
To answer literally your exact question:
def getFoo[R, A <: Foo[R]](a: A): R = a.foo
But since you don't make any use of the type A, you can actually omit it and the <: Foo[..] bound completely, retaining only the return type:
def getFoo[R](a: Foo[R]): R = a.foo
Update (the question has been changed quite significantly)
You could smuggle in an additional apply invocation that infers the return type from a separate implicit return type witness:
trait Foo[A] { def foo: A }
/** This is the thing that remembers the actual return type of `foo`
* for a given `A <: Foo[R]`.
*/
trait RetWitness[A, R] extends (A => R)
/** This is just syntactic sugar to hide an additional `apply[R]()`
* invocation that infers the actual return type `R`, so you don't
* have to type it in manually.
*/
class RetWitnessConstructor[A] {
def apply[R]()(implicit w: RetWitness[A, R]): A => R = w
}
def getFoo[A <: Foo[_]] = new RetWitnessConstructor[A]
Now it looks almost like what you wanted, but you have to provide the implicit, and you have to call getFoo[ConcreteFoo.type]() with additional pair of round parens:
object ConcreteFoo extends Foo[String] {
override def foo: String = "hey"
}
implicit val cfrw = new RetWitness[ConcreteFoo.type, String] {
def apply(c: ConcreteFoo.type): String = c.foo
}
val f = getFoo[ConcreteFoo.type]()
val x: String = f(ConcreteFoo)
I'm not sure whether it's really worth it, it's not necessarily the most straightforward thing to do. Type-level computations with implicits, hidden behind somewhat subtle syntactic sugar: that might be too much magic hidden behind those two parens (). Unless you expect that the return type of foo will change very often, it might be easier to just add a second generic argument to getFoo, and write out the return type explicitly.
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 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")
Still struggling with this.types (singleton types). Assume this scenario:
trait Sys[A <: Access] {
def in[T](v: String): AccessPrepare[A]
}
trait AccessPrepare[A <: Access] {
val a: A
def apply[T](fun: a.type => T): T
}
object Ref {
def single[A <: Access, V](v: V)(implicit a: A): Ref[A, V] = ???
}
trait Ref[A, V]
trait Access {
def set(r: Ref[this.type, Int]): Unit
}
The following fails:
def test(sys: Sys[Access]): Unit =
sys.in("v1") { implicit a =>
val r = Ref.single(44)
a.set(r)
}
because apparently r is of type Ref[Access, Int] and not Ref[a.type, Int]. My guess is the problem is that I would need a line like
def single[A <: Access, V](v: V)(implicit a: A): Ref[a.type, V] = ...
which isn't compiling as due to "illegal dependent method type"...
Any ideas how I can fix this. The demand is that I do not explicitly annotate calls with types. That is, I do not want to write Ref.single[a.type, Int](44)(a) for comprehensible reasons.
EDIT
As a clarification, with reference to answer "FYI, and to close the question" in thread Constraining an operation by matching a type parameter to an argument's path-dependent type -- what I would like to have in addition is the possibility to create objects (Refs) not by using a factory method in the Access but somewhere outside (e.g. with a new statement). Because the system cannot be limited by the definition of Access, I must be able to extend it with further objects.
You have several possibilities. With Scala 2.8/2.8.1, you can use the private option -Ydependent-method-types and then your solution with
def single[ A <: Access, V ]( v: V )( implicit a: A ) : Ref[ a.type, V ] = // ...
compiles fine.
If you want to avoid dependent method types because it's a private option, you can still make your first proposal compile by explicitly typing the call to Ref.single:
val r = Ref.single[a.type, Int](44)
You need to specify the type, though, as singleton types are never inferred. You problem is not the same as, but related to, the problem that singleton types are not inferred: see How to correctly type-annotate this HList?