NOTE: if someone can come up with a better title for what I am trying to ask - please mention or edit.
Given a wrap method:
trait MyWrapperBound {
val message: String
}
def wrap[T <: MyWrapperBound](message: String): T
I am looking for a way to describe that all all implementations of MyWrapperBound should have a constructor that takes a message: String so I can construct and return it from my wrap method.
I can think of a couple of ways to do this:
Method 1 - using an implicit:
def wrap[T <: MyWrapperBound](message: String)(implicit factory: String => T): T
This would mean that any MyWrapperBound impl. would also have to create the implicit:
case class SimpleBound(message: String) extends MyWrapperBound
object SimpleBound {
implicit def factory(message: String): SimpleBound = SimpleBound(message)
}
This would result in a fair amount of boilerplate - which I'd like to avoid.
Method 2 - macro:
def wrap[T <: MyWrapperBound](message: String): T = macro ...
The macro would take the type, assert there is a valid constructor, constructing the type if its there and throw a nice compile error if not present for the developer to go and fix (by adding a valid constructor)
My question is - being fairly new to scala, is there a simpler option that I am missing? or another option that makes more sense?
If you're amenable to typeclasses there is a slightly simpler answer involving implicits. You can accomplish what you're trying to do rather easily by adding a type parameter to MyWrapperBound and enumerating the types of messages you'd like to support using the Show typeclass. For instance, if you knew everything that you were attempting to wrap supported a map A => String, you could supply a Show[A] implicit to your wrap method like so:
trait Show[A] {
def show(a: A): String
}
trait MyWrapperBound[A] {
val message: String
}
object MyWrapperBound {
def wrap[A](a: => A)(implicit ev: Show[A]): MyWrapperBound[A] =
new MyWrapperBound[A] {
override val message: String = ev.show(a)
}
}
object ShowInstances {
case class MyDS(someInformation: List[String])
implicit val simpleShow: Show[String] = new Show[String] {
override def show(a: String): String = a
}
implicit val slightlyMoreComplexShow: Show[MyDS] = new Show[MyDS] {
override def show(a: MyDS): String = a.someInformation.mkString("[", ",", "]")
}
}
As always, the code compiles and produces the desired output. Adding more support is as easy as adding more instances to ShowInstances. This allows you to decouple the map A => String from the wrapper logic itself, so that wrap becomes a simple constructor for MyWrapperBound.
If you don't like the idea of parametrizing your MyWrapperBound with a type parameter, it's not even necessary if you're not planning to have instances of it indexed by some message type.
Related
Say I have the following trait and class:
case class Result[A](
header: String,
data: A
)
trait WebClient {
def doSomething[A : TypeTag](name: String): Future[Result[A]]
}
In this example, doSomething is the polymorphic method in question. How can I create a MockWebClient which implements WebClient and have minimal behavior? (The most minimal behavior being doing nothing.) Preferably, I don't want to return a Future.failed because the result shouldn't signify a failure, semantically. Also, I don't want to change the A type of Result[A] to be covariant or contravariant (i.e. +A or -A) because it doesn't make a lot of sense in the context.
Here's my best attempt (which still doesn't compile). It uses a generic class with a generic factory to simulate the return value of the doSomething method. However, I cannot find the correct relationship between A and B:
class MockWebClient[A](val factory: () => Result[A]) extends WebClient {
override def doSomething[B >: A : TypeTag](name: String): Future[Result[B]] = {
Future.successful(factory())
}
}
Also, I have used mockito-scala, but it doesn't work because of type erasure. scalamock also seems interesting, but I would like to know if there is a way to make something similar to my solution work.
If you are sure data field will not be used in the test you could trick the compiler with null.asInstanceOf[A]
val mockWebClient = new WebClient {
override def doSomething[A](name: String): Future[Result[A]] =
Future.successful(Result(name, null.asInstanceOf[A]))
}
If A forms a Monoid you could do it in a type-safe manner with something like
import cats.Monoid
import cats.implicits._
trait WebClient {
def doSomething[A: Monoid](name: String): Future[Result[A]]
}
val mockWebClient = new WebClient {
override def doSomething[A: Monoid](name: String): Future[Result[A]] =
Future.successful(Result(name, implicitly[Monoid[A]].empty))
}
mockWebClient.doSomething[String]("woohoo")
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()
Ideally I'd like to be able to do the following in Scala:
import Builders._
val myBuilder = builder[TypeToBuild] // Returns instance of TypeToBuildBuilder
val obj = myBuilder.methodOnTypeToBuildBuilder(...).build()
In principle the goal is simply to be able to 'map' TypeToBuild to TypeToBuildBuilder using external mapping definitions (i.e. assume no ability to change these classes) and leverage this in type inferencing.
I got the following working with AnyRef types:
import Builders._
val myBuilder = builder(TypeToBuild)
myBuilder.methodOnTypeToBuildBuilder(...).build()
object Builders {
implicit val typeToBuildBuilderFactory =
new BuilderFactory[TypeToBuild.type, TypeToBuildBuilder]
def builder[T, B](typ: T)(implicit ev: BuilderFactory[T, B]): B = ev.create
}
class BuilderFactory[T, B: ClassTag] {
def create: B = classTag[B].runtimeClass.newInstance().asInstanceOf[B]
}
Note that the type is passed as a function argument rather than a type argument.
I'd be supremely happy just to find out how to get the above working with Any types, rather than just AnyRef types. It seems this limitation comes since Singleton types are only supported for AnyRefs (i.e. my use of TypeToBuild.type).
That being said, an answer that solves the original 'ideal' scenario (using a type argument instead of a function argument) would be fantastic!
EDIT
A possible solution that requires classOf[_] (would really love not needing to use classOf!):
import Builders._
val myBuilder = builder(classOf[TypeToBuild])
myBuilder.methodOnTypeToBuildBuilder(...).build()
object Builders {
implicit val typeToBuildBuilderFactory =
new BuilderFactory[classOf[TypeToBuild], TypeToBuildBuilder]
def builder[T, B](typ: T)(implicit ev: BuilderFactory[T, B]): B = ev.create
}
class BuilderFactory[T, B: ClassTag] {
def create: B = classTag[B].runtimeClass.newInstance().asInstanceOf[B]
}
Being able to just use builder(TypeToBuild) is really just a win in elegance/brevity. Being able to use builder[TypeToBuild] would be cool as perhaps this could one day work (with type inference advancements in Scala):
val obj: TypeToBuild = builder.methodOnTypeToBuildBuilder(...).build();
Here is a complete, working example using classOf: http://ideone.com/94rat3
Yes, Scala supports return types based on the parameters types. An example of this would be methods in the collections API like map that use the CanBuildFrom typeclass to return the desired type.
I'm not sure what you are trying to do with your example code, but maybe you want something like:
trait Builder[-A, +B] {
def create(x: A): B
}
object Builders {
implicit val int2StringBuilder = new Builder[Int, String] {
def create(x: Int) = "a" * x
}
def buildFrom[A, B](x: A)(implicit ev: Builder[A, B]): B = ev.create(x)
}
import Builders._
buildFrom(5)
The magic with newInstance only works for concrete classes that have a constructor that takes no parameters, so it probably isn't generic enough to be useful.
If you're not afraid of implicit conversions, you could do something like this:
import scala.language.implicitConversions
trait BuilderMapping[TypeToBuild, BuilderType] {
def create: BuilderType
}
case class BuilderSpec[TypeToBuild]()
def builder[TypeToBuild] = BuilderSpec[TypeToBuild]
implicit def builderSpecToBuilder[TypeToBuild, BuilderType]
(spec: BuilderSpec[TypeToBuild])
(implicit ev: BuilderMapping[TypeToBuild, BuilderType]) = ev.create
case class Foo(count: Int)
case class FooBuilder() {
def translate(f: Foo) = "a" * f.count
}
implicit val FooToFooBuilder = new BuilderMapping[Foo, FooBuilder] {
def create = FooBuilder()
}
val b = builder[Foo]
println(b.translate(Foo(3)))
The implicit conversions aren't too bad, since they're constrained to these builder-oriented types. The conversion is needed to make b.translate valid.
It looked like wingedsubmariner's answer was most of what you wanted, but you didn't want to specify both TypeToBuild and BuilderType (and you didn't necessarily want to pass a value). To achieve that, we needed to break up that single generic signature into two parts, which is why the BuilderSpec type exists.
It might also be possible to use something like partial generic application (see the answers to a question that I asked earlier), though I can't put the pieces together in my head at the moment.
I'll resort to answering my own question since a Redditor ended up giving me the answer I was looking for and they appear to have chosen not to respond here.
trait Buildable[T] {
type Result
def newBuilder: Result
}
object Buildable {
implicit object ABuildable extends Buildable[A] {
type Result = ABuilder
override def newBuilder = new ABuilder
}
implicit object BBuildable extends Buildable[B] {
type Result = BBuilder
override def newBuilder = new BBuilder
}
}
def builder[T](implicit B: Buildable[T]): B.Result = B.newBuilder
class ABuilder {
def method1() = println("Call from ABuilder")
}
class BBuilder {
def method2() = println("Call from BBuilder")
}
Then you will get:
scala> builder[A].method1()
Call from ABuilder
scala> builder[B].method2()
Call from BBuilder
You can see the reddit post here: http://www.reddit.com/r/scala/comments/2542x8/is_it_possible_to_define_a_function_return_type/
And a full working version here: http://ideone.com/oPI7Az
class foo(val x:Int){
def convertToInt(z:string) = {do somthing to convert a string to an integer}
def this(y:string) = this(convertToInt(y))
}
calling convertToInt in auxiliary constructor (this(y:string)) causes this error:
error: not found: value convertToInt
I know I can use a singleton object and pack all static functions like convertToInt into it, but is it a good solution?
object foo{
def convertToInt(z:string) = {do somthing to convert a string to an integer}
}
class foo(val x:Int){
def this(y:string) = this(foo.convertToInt(y))
}
I think in this case the best solution would be to use factory methods instead of public constructor.
So you can define your constructor private and provide factory apply methods in companion object:
class Foo private (val x:Int)
object Foo {
def apply(i: Int) = new Foo(i)
def apply(s: String) = new Foo(convertToInt(s))
def convertToInt(s: String) = s.toInt
}
println(Foo(512).x)
println(Foo("256").x)
You can find more information about constructor vs factory method here:
Constructors vs Factory Methods
It's the same for Scala.
Update
As an example of alternative solution I made very generic solution. Foo class can now work with any class that ever existed or can be created in future, assuming, that this type can be converted (you can define how it should be converted) to/from Int:
trait Convertable[From, To] {
def convert(from: From): To
}
object Convertable {
implicit val intString = new Convertable[Int, String] {
def convert(from: Int) = from toString // your logic here
}
implicit val stringInt = new Convertable[String, Int] {
def convert(from: String) = from toInt // your logic here
}
implicit def self[T] = new Convertable[T, T] {
def convert(from: T) = from
}
}
case class Foo[T](original: T)(implicit toInt: Convertable[T, Int], fromInt: Convertable[Int, T]) {
val x: Int = toInt convert original
def toOriginal = fromInt convert x
}
println(Foo(512) x)
println(Foo("256") x)
(I could define toOriginal by just returning = original, but it would be too boring :)
As you can see, this solution is generic and more complicated. But as far as I saw, many application need some kind of conversion between different primitive values and/or classes. So in many cases it's sutable (and may be event considered very good) solution for many cases and may be for your also. But it's often impossible to tell what's "the best" solution for all possible cases.
by using angle's offer about factory method instead of Auxiliary Constructor:
class Foo(val s:String) {
val s = ""
def bar2:String = s+s
def bar3:List[Char] = s.toList
}
object Foo extends{
def bar1(y:List[Char]):String =y.mkString
def apply(s:String)= new Foo(s)
def apply(y:List[Char])= new Foo(bar1(y))
}
client code:
val foo1 = Foo(List('a','b'))
println(foo1.s)
println(foo1.bar2)
println(foo1.bar3)
Your solution isn't that bad. After all, convertToInt is similar to a static method in Java. Personally I don't like auxiliary constructors, so I'd normally prefer Easy Angels solution as well. However if you plan to inherit from your class later, the companion object approach won't "scale" for the derived class, you would have to reimplement that method. In that case you should stick with your solution.
Theoretically you could put that method in a separate trait and extend it, but I wouldn't recommend this. Using inheritance should be limited to cases when there is a real dependency, not just for "convenience".