In Scala v 2.7.7
I have a file with
class Something[T] extends Other
object Something extends OtherConstructor[Something]
This throws the error:
class Something takes type parameters
object Something extends OtherConstructor[Something] {
However, I can't do this
object Something[T] extends OtherConstructor[Something[T]]
It throws an error:
error: ';' expected but '[' found.
Is it possible to send type parameters to object? Or should I change and simply use Otherconstructor
You could use:
object Something extends OtherConstructor[Something[_]]
You will of course be restricted by having an existential type with no upper bound in place instead of a concrete type. This solution may not make sense and you might need one object per concrete type T, for those T's which you care about, e.g.
object StringSomething extends OtherConstructor[Something[String]]
But then this has the (possible) disadvantage that StringSomething is not the companion object of Something.
However, my advice would be don't start messing about designing generic APIs (especially self-referential ones like the above) unless you really, really know what you are doing. It will almost certainly end in tears and there are plenty of CORE Java API's which are terrible because of the way generics have been added (the RowSorter API on JTable being one example)
You can solve the general problem of needing object Foo[T] by moving the type parameter to the methods in object Foo:
class Foo[T](t1: T, t2: T)
object Foo {
def apply[T](x: T): Foo[T] = new Foo(x, x)
def apply[T](x: T, y: T): Foo[T] = new Foo(x, y)
}
If you really need one object per T, you can make a class, and have the type-free companion return it from apply.
class Foo[T](t1: T, t2: T)
class FooCompanion[T] {
def apply(x: T): Foo[T] = new Foo(x, x)
def apply(x: T, y: T): Foo[T] = new Foo(x, y)
}
object Foo {
def apply[T] = new FooCompanion[T]
}
object demo extends App {
val x: Foo[Double] = Foo.apply.apply(1.23) // this is what is really happening
val y: Foo[Int] = Foo[Int](123) // with the type both apply calls are automatic
}
Note this will re-construct the Foo[T] companion on each call so you would want to keep it light and stateless.
An explicit solution the the problem above:
class Other
class OtherConstructor[O <: Other] {
def apply(o: O): O = o // constructor 1 in base class
}
class Something[T](value: T) extends Other
class SomethingConstructor[T] extends OtherConstructor[Something[T]] {
def apply(o: T, s: String) = new Something[T](o) // constructor 2 in subclass
}
object Something {
def apply[T] = new SomethingConstructor[T] // the "constructor constructor" method
}
object demoX extends App {
val si = new Something(123)
val sd = new Something(1.23)
val si1: Something[Int] = Something[Int](si) // OtherConstructor.apply
val sd1: Something[Double] = Something[Double](1.23, "hello") // SomethingConstructor[Double].apply
}
An object has to have a concrete type. The Scala object contruct is not a exception to this rule.
A valid definition is
object Something extends OtherConstructor[Something[T]] { }
where T is some concrete type.
Thanks for the answers
object Something extends OtherConstructor[Something[_]]
seems to be compiling (although I have yet to run/test that :-))
#oxbow_lakes, I've followed your advice - of avoiding the type system - till now but I've got to do it!!!
I've been studying existential types, type-erasure and all that but its still not in my grasp :-(
Related
Let's imagine I have the following base trait and case classes
sealed trait BaseTrait
case class Foo(x: Integer = 1) extends BaseTrait
case class Bar(x: String = "abc") extends BaseTrait
I would like to create a generic interface for classes which can process BaseTrait instances, something like the following
class FooProcessor(val model: FooModel) extends BaseProcessor[Foo] {
val v: Option[Foo] = model.baseVar
}
class BarProcessor(val model: BarModel) extends BaseProcessor[Bar] {
val v: Option[Bar] = model.baseVar
}
For this I have the following traits
trait BaseModel[T <: BaseTrait] {
var baseVar: Option[T] = None
}
trait BaseProcessor[T <: BaseTrait] {
def model: BaseModel[T]
def process(x: T): Unit = model.baseVar = Option(x)
}
The model definitions are the following
class FooModel extends BaseModel[Foo]
class BarModel extends BaseModel[Bar]
Now lets imagine I have the following processors somewhere in my app
val fooProcessor = new FooProcessor(new FooModel)
val barProcessor = new BarProcessor(new BarModel)
I would like to handle them in a somewhat generic way, like this
def func[T <: BaseTrait](p: T) {
val c/*: BaseProcessor[_ >: Foo with Bar <: BaseTrait with Product with Serializable]*/ = p match {
case _: Foo => fooProcessor
case _: Bar => barProcessor
c.process(p)
}
The compiler is not really happy about the last line, it says
type mismatch;
found : T
required: _1
If I understand correctly this is basically the compiler trying to prevent barProcessor.process(Foo()) from happening. I've tried a couple of solutions to get around this and achieve the desired behavior:
the simplest way around this is calling the proper *Processor.process with the proper BaseTrait instance inside the match case, which seems to defy the whole point of handling them in a somewhat generic way
use an abstract type in the BaseModel and BaseProcessor, which one hand got rid of the somewhat unneeded type parameter in BaseModel but the compilers complaint is still valid and I was not able to figure out if it's possible to get that to work
get rid of the type parameter and contraint from the BaseModel, and just do a type cast in the processor to get the proper type, but the explicit type cast also isn't really what I was hoping for
Like so:
trait BaseModel {
var baseVar: Option[BaseTrait] = None
}
trait BaseProcessor[T <: BaseTrait] {
def model: BaseModel
def process(x: T): Unit = model.baseVar = Some(x)
def getBaseValue: T = model.baseVar.map(_.asInstanceOf[T])
}
I guess one could also somehow convince the compiler that the two types (T of the Processor and T of the func parameter p) are equivalent, but that also seems like an overkill (and I'm also not really sure how it can be done).
So my question is the following: is it possible to do what I'm trying to achieve here (managing processors in a uniform way + each processor knows their specific type of BaseTrait) in a somewhat easy fashion? Is there a better model for this which I'm missing?
Update
As per Tim's answer making the controllers implicit solves the problem, however if you want to have a class where you define your controllers + have 'func' on it's interface the compiler no longer seems to properly resolve the implicits. So if I try to do something like this
class ProcessorContainer {
implicit val fooProcessor = new FooProcessor(new FooModel)
implicit val barProcessor = new BarProcessor(new BarModel)
def func[T <: BaseTrait](p: T) = typedFunc(p)
private def typedFunc[T <: BaseTrait](p: T)(implicit processor: BaseProcessor[T]) =
processor.process(p)
}
class Test {
val processorContainer = new ProcessorContainer
processorContainer.func(Foo())
processorContainer.func(Bar())
}
I get the following compile error (one for Foo and one for Bar):
could not find implicit value for parameter processor: BaseProcessor[Foo]
not enough arguments for method
Is there a way around this? I could of course expose the controllers so they can be passed in implicitly, however I'd prefer not doing that.
You can create a simple typeclass by making the processors implicit and passing them as an extra argument to func:
implicit val fooProcessor = new FooProcessor(new FooModel)
implicit val barProcessor = new BarProcessor(new BarModel)
def func[T <: BaseTrait](p: T)(implicit processor: BaseProcessor[T]) =
processor.process(p)
If you pass a Foo to func it will call FooProcessor.process on it, and if you pass a Bar to func it will call BarProcessor on it.
How can I achieve this:
final case class ChairId(id: String)
trait GeneratorLike[TO, TC <: AbstractId] {
val prefix: String
def generate(): TC = TO.apply(prefix + "-" + UUID.randomUUID())
}
implicit object ChairIdGenerator extends GeneratorLike[ChairId.type, ChairId] {
val prefix: String = "CHAIR"
}
implicit def IdFn[TO, TC <: AbstractId](x: TO)(implicit ev: GeneratorLike[TO, TC]): GeneratorLike[TO, TC] = ev
//right now I can call:
ChairId.generate()
I don't want to define companion object for that situation and I wondered if there is a chance to extend object with use of implicits?
When I do (I use TO as TypeObject and TC as TypeClass naming) idFn[TO, TC] I want TO to be object that implements def apply(id: String): TC can I enforce that? And how would I get to use this function? It feels totally impossible to call function on type parameter :/
It is impossible to call a method on a type parameter, because it represents a type and not an object. You can call a method on an object, because it is something that exists, but a type is an abstract concept. I don't know what your motivation is for wanting to implicitly add generate() to companion objects, because it actually requires just as much code to define an implicit GeneratorLike than it does to define the companion for ChairId.
If you force GeneratorLike to have an apply method (which can be implemented by case class apply), and remove the first type parameter, this will work.
trait GeneratorLike[TC <: AbstractId] { this: Singleton =>
val prefix: String
def apply(id: String): TC
def generate(): TC = apply(prefix + "-" + UUID.randomUUID())
}
abstract class AbstractId
final case class ChairId(id: String) extends AbstractId
object ChairId extends GeneratorLike[ChairId] {
val prefix = "CHAIR"
}
scala> ChairId.generate()
res0: ChairId = ChairId(CHAIR-60bb01c7-af95-46c7-af45-0b3fa78b3080)
Structural typing is not a particularly good idea on the JVM, so always try to avoid the def test(x: {def apply(s: String)}): TC type stuff because it is implemented using reflection which can be a dog performance wise.
Second, you should probably avoid using val inside a trait. Read here.
The approach you have considered is actually the right one, and namely type classes.
trait HasGenerator[T] {
def apply(uuid: String): T
def generate[T : Generator] = apply(Generator[T].generate)
}
final case class ChairId(id: String)
object ChairId extends HasGenerator[ChairId]
trait Generator[TO] {
def prefix: String
def generate(): String = prefix + "-" + UUID.randomUUID()
def apply(): String = generate
}
object Generator {
def apply[T : Generator] = implicitly[Generator[T]]
}
// Notice .type is not necessary
implicit object ChairIdGenerator extends Generator[ChairId] {
override def prefix = "CHAIR"
}
Why not just use:
ChairId(Generator[ChairId])
This all seems like overkill though so you can quite easily somehow. It's worth fleshing out your requirements a bit more because type classes don't really seem super necessary just yet. You could just do with:
Update
If you use something like the HasGenerator that I have added above in conjunction with the companion object, you can now successfully call ChairId.generate()
I have few classes which do not derive from any superclass. They all have bunch of same methods defined. For example,
class A {
def getMsgNum = 1
}
class B {
def getMsgNum = 2
}
I would like to write a generic function that will return message num based on object function is called with. So something like,
def getMsgNum[T](t: T) = t.getMsgNum
I think that because of type erasure I cannot expect that to work but I was looking at view bound and context bound with ClassTag but that still does not work.
def getType[T: ClassTag](msg: T) = {
msg.getMsgNum
}
I come from C++ background and I am trying to achieve something to the effect of template compilation for every type.
Thanks for your time!
I personally prefer adhoc polymorphism with TypeClass (http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html) pattern. I think it will be much more "true scala way" solution for this kind of problem. Also structural typing more expensive at runtime because it use reflection for field access.
class A
class B
trait ToMsgNum[T] {
def getMsgNum: Int
}
implicit object AToMsgNum extends ToMsgNum[A] {
def getMsgNum = 1
}
implicit object BToMsgNum extends ToMsgNum[B] {
def getMsgNum = 2
}
def getMsgNum[T: ToMsgNum](t: T) =
implicitly[ToMsgNum[T]].getMsgNum
println(getMsgNum(new A))
println(getMsgNum(new B))
def getMsgNum[T](t: T)(implicit ev: T => { def getMsgNum: Int }) = t.getMsgNum
where { def getMsgNum: Int } is a structural type. From the documentation:
A structural type is a type of the form Parents { Decls } where Decls contains declarations of new members that do not override any member in Parents.
and
Structural types provide great flexibility because they avoid the need to define inheritance hierarchies a priori
Please note that the above solution uses an implicit reflective call to access the field of the structural type, a language feature that has to be explicitly enabled by adding the import
import scala.language.reflectiveCalls
This is not too different from Eugene's solution but I think it's a bit clearer:
// predefined classes you have no access to
class Foo { def someMethod = "foo" }
class Bar { def someMethod = "bar" }
there's no way in Scala other than reflection or structural types (which is reflection in disguise) to generically call someMethod on these types. The way this can be made to work though, is by defining adapter objects that know how to deal with each type individually, and you then make generic calls on those instead:
trait HasSomeMethod[T] { def someMethod(x: T): String }
object FooHasSomeMethod extends HasSomeMethod[Foo] { def someMethod(x: Foo) = x.someMethod }
object BarHasSomeMethod extends HasSomeMethod[Bar] { def someMethod(x: Bar) = x.someMethod }
now you can pass one of those adapter objects into the method that needs generic access to Foo#someMethod and Bar#someMethod:
def invokeSomeMethod[T](x: T)(adapter: HasSomeMethod[T]) =
adapter.someMethod(x)
invokeSomeMethod(new Foo)(FooHasSomeMethod) // returns "foo"
invokeSomeMethod(new Bar)(BarHasSomeMethod) // returns "bar"
(we could have used a single parameter list here but later we'll nede 2 lists anyway)
however, this is obviously not as useful as we'd like as we have to pass in the adapter manually. Let's introduce implicits to make Scala automatically look up the right adapter object and pass that in to our generic but inheritance'less method:
implicit object FooHasSomeMethod extends HasSomeMethod[Foo] { ... }
implicit object BarHasSomeMethod extends HasSomeMethod[Bar] { ... }
def invokeSomeMethod[T](x: T)(implicit adapter: HasSomeMethod[T]) =
adapter.someMethod(x)
now these work:
invokeSomeMethod(new Foo) // returns "foo"
invokeSomeMethod(new Bar) // returns "bar"
The above 2 calls get translated automatically to the longer calls in the previous version; Scala looks up suitable values for the implicit adapter parameter automatically from the implicit objects (and also vals and defs, to be precise) available in the "environment" of the call.
You can also define invokeSomeMethod like this, which is just syntactic sugar over the above definition:
def invokeSomeMethod[T: HasSomeMethod](x: T) =
implicitly[HasSomeMethod[T]].someMethod(x)
or, since T: HasSomeMethod auto-generates a second parameter list implicit evidence$1: HasSomeMethod[T], this also works:
def invokeSomeMethod[T: HasSomeMethod](x: T) =
evidence$1.someMethod(x)
The above "pattern" is known as Type Classes. So for example the T: HasSomeMethod bit can be read as "some type T that belongs to the type class HasSomeMethod" (or "...has been made an instance of the type class HasSomeMethod").
For more on Type Classes, see e.g. http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html.
You can also define the HasSomeMethod type class instance for classes that don't even have someMethod nor bear no other resemblance to Foo and Bar whatsoever, if needed:
implicit object IntHasSomeMethod extends HasSomeMethod[Int] {
def someMethod(x: Int) = "this is an int: " + x
}
invokeSomeMethod(3) // returns "this is an int: 3"
If you need to define an instance of that type class for many classes, you can have a helper (with a name that matches the type class, for niceness):
def HasSomeMethod[T](fn: T => String) = new HasSomeMethod[T] {
def someMethod(x: T) = fn(x)
}
now you can define type class instances (adapters) very concisely:
implicit val FooHasSomeMethod = HasSomeMethod[Foo](_.someMethod)
implicit val BarHasSomeMethod = HasSomeMethod[Bar](_.someMethod)
implicit val IntHasSomeMethod = HasSomeMethod[Int]("this is an int: " + _)
implicit val PersonHasSomeMethod = HasSomeMethod[Person](_.name)
// etc
If you dont want to use structural type (reflection) and implicit, how about create Adaptor on top of it, so you own method getMsgNum will implement based on the Adaptor instead of already existing class.
class A {
def getMsgNum = 1
}
class B {
def getMsgNum = 2
}
class C {
def getMsgNum = 3
}
trait Adaptor[T] {
def getMsgNum: Int
}
class AdaptorA(t: A) extends Adaptor[A] {
def getMsgNum = t.getMsgNum
}
class AdaptorB(t: B) extends Adaptor[B] {
def getMsgNum = t.getMsgNum
}
class AdaptorC(t: C) extends Adaptor[C] {
def getMsgNum = t.getMsgNum
}
def getMsgNum[T](t: Adaptor[T]) = t.getMsgNum
getMsgNum(new AdaptorA(new A)) //1
getMsgNum(new AdaptorB(new B)) //2
getMsgNum(new AdaptorC(new C)) //3
The type class pattern in Scala involves defining a trait such as:
trait Show[T] {
def show(obj: T): String
}
Then you can define instantiations of this type class as such:
object Show {
implicit val string = new Show[String] {
def show(obj: String): String = obj
}
implicit object BooleanShow extends Show[Boolean] {
def show(obj: Boolean): String = obj.toString
}
}
The advantage of defining these instantiations for basic types in the companion object is that they are automatically in scope whenever the type class is concerned (roughly).
Functionally it would appear defining the instantiation as an implicit val or an implicit object does not change much.
Is there a difference? Is one way better than the other?
There is actually more than the type names between val and object.
You know, object in Scala is something like a singleton in Java.
Maybe you thought that both string and BooleanShow are in an object not a class so they have no difference, but that's not true.
They are val and object no matter what.
Try this in Scala REPL.
trait Show[T] {
def show(obj: T): String
}
object Show {
println("!! Show created")
implicit val string = new Show[String] {
println("!! string created")
def show(obj: String): String = obj
}
implicit object BooleanShow extends Show[Boolean] {
println("!!BooleanShow created")
def show(obj: Boolean): String = obj.toString
}
}
If only the definition is done, then no printlns are executed afterwards, since Show is a singleton in effect. It's not created yet.
Next, execute Show in Scala REPL.
scala> Show
!! Show created
!! string created
res0: Show.type = Show$#35afff3b
You see, printlns in Show and Show.string were called, but the one in Show.BooleanShow was not.
You can execute Show.BooleanShow next in Scala REPL.
scala> Show.BooleanShow
!!BooleanShow created
res1: Show.BooleanShow.type = Show$BooleanShow$#18e419c5
Show.BooleanShow was initialized at last. It is a singleton, so it is lazy.
Basically, your question is the same as val and object inside a scala class? except that your val and object are defined in an object, but the linked question tries to find differences val and object defined in a class and the method in val uses reflection (but yours uses overriding, so no reflection is involved). implicit basically does not make difference in what they are.
I think you already know the difference between class and object. Further information can be found in the linked question.
Since they say always to use explicit types for implicits, prefer val over object.
Compare Why can't Scala find my typeclass instance defined implicitly in the companion object, when the typeclass is not in a dedicated source file? where it makes a difference.
Make it lazy if necessary.
Elaboration:
scala> trait T
defined trait T
scala> object X { implicitly[T] ; object O extends T }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; object O extends T }
^
scala> object X { implicitly[T] ; implicit object O extends T }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; implicit object O extends T }
^
scala> object X { implicitly[O.type] ; implicit object O extends T }
defined object X
scala> object X { implicitly[T] ; implicit object O extends T ; implicit def y = O }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; implicit object O extends T ; implicit def y = O }
^
scala> object X { implicitly[T] ; implicit object O extends T ; implicit def y: T = O }
defined object X
The inferred type of O is the singleton type O.type.
With val x = new X { } you are creating an anonymous subclass of X, whereas with object x extends X you create a "proper" subclass. I would think that the overhead of an object is minimal, and as #applicius points out, it has proper name. Therefore I suggest to go for the object in this case.
I have been working on an issue with implicit conversion for days now, but somehow I just cannot figure out what I am doing wrong. I read through all the other questions on SO that deal with implicits but I still don't understand what the problem is.
As an example, let's consider a Java interface like this(T extends Object for brevity):
public interface JPersistable<T extends Object> {
public T persist(T entity);
}
In scala, I do the following:
case class A()
case class B() extends A
case class C()
case class D() extends C
trait Persistable[DTOType <: A, EntityType <: C] {
// this would be implemented somewhere else
private def doPersist(source: EntityType): EntityType = source
// this does not implement the method from the Java interface
private def realPersist(source: DTOType)(implicit view: DTOType => EntityType): EntityType = doPersist(source)
// this DOES implement the method from the Java interface, however it throws:
// error: No implicit view available from DTOType => EntityType.
def persist(source: DTOType): EntityType = realPersist(source)
}
case class Persister() extends Persistable[B, D] with JPersistable[B]
object Mappings {
implicit def BToD(source: B): D = D()
}
object Test {
def main(args: Array[String]) {
import Mappings._
val persisted = Persister().persist(B())
}
}
As stated in the comment, I get an exception at compile time. I guess my questions are:
1) Why do I need to specify the implicit conversion on the doRealPersist explicitly? I expected the conversion to happen even if I do the following:
trait Persistable[DTOType <: A, EntityType <: C] {
// this would be implemented somewhere else
private def doPersist(source: EntityType): EntityType = source
def persist(source: DTOType): EntityType = doPersist(source)
}
However, this does not compile either.
2) Why does compilation fail at persist and not at the actual method call (val persisted = Persister().persist(B()))? That should be the first place where the actual type of EntityType and DTOType are known, right?
3) Is there a better way to do what I am trying to achieve? Again, this is not the actual thing I am trying to do, but close enough.
Apologies in advance if this question is ignorant and thanks a lot in advance for your help.
You need to make the conversion available within the trait. You can't pass it in from the outside implicitly because the outside doesn't know that persist secretly requires realPersist which requires an implicit conversion. This all fails even without considering JPersistable.
You can for example add
implicit def view: DTOType => EntityType
as a method in the trait and it will then compile. (You can drop realPersist then also.)
Then you need a way to get that view set. You can
case class Persister()(implicit val view: B => D) extends Persistable[B,D]
and then you're all good. (The implicit val satisfies the implicit def of the trait.)
But now you have bigger problems: your Java interface signature doesn't match your Scala signature. The equivalent Scala is
trait JPersistable[T <: Object] { def persist(t: T): T }
See how persist takes and returns the same type? And see how it does not in your Scala class? That's not going to work, nor should it! So you have to rethink exactly what you're trying to accomplish here. Maybe you just want to make the implicit conversion available--not pass it to the method!--and have Scala apply the implicit conversion for you so that you think you've got a persist that maps from DTOType to EntityType, but you really just have the EntityType to EntityType transform that the Java interface requires.
Edit: for example, here's a working version of what you posted just using standard implicit conversion:
trait JPer[T] { def persist(t: T): T }
class A
case class B() extends A
class C
case class D() extends C
trait Per[Y <: C] extends JPer[Y] {
private def doIt(y: Y): Y = y
def persist(y: Y) = doIt(y)
}
case class Perer() extends Per[D] // "with JPer" wouldn't add anything!
object Maps { implicit def BtoD(b: B): D = D() }
object Test extends App {
import Maps._
val persisted = Perer().persist(B())
}
Pay attention to which types are used where! (Who takes B and who takes D and which direction do you need a conversion?)