Object converting string into "A" - scala

I would like to write a class looking like this:
class Store[+A](dest: Symbol)(implicit c: String => A) extends Action(dest) {
override def update(options: HashMap[Symbol,Any], arg: String): Unit = {
options += ((dest -> c(arg)))
}
}
object Store {
def apply[A](dest: Symbol)(c: String=>A) = new Store[A](dest)(c)
def apply[A](dest: Symbol) = new Store[A](dest)
}
Doing so, I have a few problems:
Using implicit with strings causes no end of trouble
Anyway, the system doesn't find the implicit if they are defined in my module, they would need to be defined in the module creating the class
the second apply method of the Store object just doesn't compile as A will be erased so the compiler has no way of finding a conversion from String to A
How would you create such an object that convert a string to some other type? I wouldn't want the user of the library to enter the type rwice (i.e. by specifying both the type and the conversion function).

I don't understand what you are trying with the second apply. To me, it looks like the first apply should have the implicit keyword, and you'd be done with it. You can either pass the parameter explicitly, or leave it out if an implicit is present. Also, you wouldn't need to pass c explicitly, since you'd already have it implicitly in the scope of the first apply.
I'd venture the second apply doesn't compile because there's no implicit String => A available in the scope of object Store.

Related

Implicit object works inline but not when it is imported

I am using avro4s to help with avro serialization and deserialization.
I have a case class that includes Timestamps and need those Timestamps to be converted to nicely formatted strings before I publish the records to Kafka; the default encoder is converting my Timestamps to Longs. I read that I needed to write a decoder and encoder (from the avro4s readme).
Here is my case class:
case class MembershipRecordEvent(id: String,
userHandle: String,
planId: String,
teamId: Option[String] = None,
note: Option[String] = None,
startDate: Timestamp,
endDate: Option[Timestamp] = None,
eventName: Option[String] = None,
eventDate: Timestamp)
I have written the following encoder:
Test.scala
def test() = {
implicit object MembershipRecordEventEncoder extends Encoder[MembershipRecordEvent] {
override def encode(t: MembershipRecordEvent, schema: Schema) = {
val dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
val record = new GenericData.Record(schema)
record.put("id", t.id)
record.put("userHandle", t.userHandle)
record.put("teamId", t.teamId.orNull)
record.put("note", t.note.orNull)
record.put("startDate", dateFormat.format(t.startDate))
record.put("endDate", if(t.endDate.isDefined) dateFormat.format(t.endDate.get) else null)
record.put("eventName", t.eventName.orNull)
record.put("eventDate", dateFormat.format(t.eventDate))
record
}
}
val recordInAvro2 = Encoder[MembershipRecordEvent].encode(testRecord, AvroSchema[MembershipRecordEvent]).asInstanceOf[GenericRecord]
println(recordInAvro2)
}
If I declare the my implicit object in line, like I did above, it creates the GenericRecord that I am looking for just fine. I tried to abstract the implicit object to a file, wrapped in an object, and I import Implicits._ to use my custom encoder.
Implicits.scala
object Implicits {
implicit object MembershipRecordEventEncoder extends Encoder[MembershipRecordEvent] {
override def encode(t: MembershipRecordEvent, schema: Schema) = {
val dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
val record = new GenericData.Record(schema)
record.put("id", t.id)
record.put("userHandle", t.userHandle)
record.put("teamId", t.teamId.orNull)
record.put("note", t.note.orNull)
record.put("startDate", dateFormat.format(t.startDate))
record.put("endDate", if(t.endDate.isDefined) dateFormat.format(t.endDate.get) else null)
record.put("eventName", t.eventName.orNull)
record.put("eventDate", dateFormat.format(t.eventDate))
record
}
}
}
Test.scala
import Implicits._
val recordInAvro2 = Encoder[MembershipRecordEvent].encode(testRecord, AvroSchema[MembershipRecordEvent]).asInstanceOf[GenericRecord]
println(recordInAvro2)
It fails to use my encoder (doesn't hit my breakpoints). I have tried a myriad of things to try and see why it fails to no avail.
How can I correctly import an implicit object?
Is there a simpler solution to encode my case class's Timestamps to Strings without writing an encoder for the entire case class?
TL;DR
As suggested in one of the comments above, you can place it in the companion object.
The longer version:
Probably you have another encoder, that is used instead of the encoder you defined in Implicits.
I'll quote some phrases from WHERE DOES SCALA LOOK FOR IMPLICITS?
When a value of a certain name is required, lexical scope is searched for a value with that name. Similarly, when an implicit value of a certain type is required, lexical scope is searched for a value with that type.
Any such value which can be referenced with its “simple” name, without selecting from another value using dotted syntax, is an eligible implicit value.
There may be more than one such value because they have different names.
In that case, overload resolution is used to pick one of them. The algorithm for overload resolution is the same used to choose the reference for a given name, when more than one term in scope has that name. For example, println is overloaded, and each overload takes a different parameter type. An invocation of println requires selecting the correct overloaded method.
In implicit search, overload resolution chooses a value among more than one that have the same required type. Usually this entails selecting a narrower type or a value defined in a subclass relative to other eligible values.
The rule that the value must be accessible using its simple name means that the normal rules for name binding apply.
In summary, a definition for x shadows a definition in an enclosing scope. But a binding for x can also be introduced by local imports. Imported symbols can’t override definitions of the same name in an enclosing scope. Similarly, wildcard imports can’t override an import of a specific name, and names in the current package that are visible from other source files can’t override imports or local definitions.
These are the normal rules for deciding what x means in a given context, and also determine which value x is accessible by its simple name and is eligible as an implicit.
This means that an implicit in scope can be disabled by shadowing it with a term of the same name.
Now I'll state the companion object logic:
Implicit syntax can avoid the import tax, which of course is a “sin tax,” by leveraging “implicit scope”, which depends on the type of the implicit instead of imports in lexical scope.
When an implicit of type T is required, implicit scope includes the companion object T:
When an F[T] is required, implicit scope includes both the companion of F and the companion of the type argument, e.g., object C for F[C].
In addition, implicit scope includes the companions of the base classes of F and C, including package objects, such as p for p.F.

How to declare variable argument abstract function in Scala

I m trying to declare function in trait that takes variable number of argument and during implementation of the trait I would expand the number of arguments. How can this done in Scala
I am expecting to come up with code like below.
trait Column {
def rule
}
case object FirstColumn extends Column{
def rule(s: String) : String
}
case object SecondColumn extends Column{
def rule(s1: String, s2: String) : String
}
I have tried using Strings* , but it is not allowing me to expand my number of arguments during implementation. I understand there are various way to handle this problem but i am specifically looking to have above signature for my team to write functions.
This is primarily expanding on my comment on the question. This answer gets you about as close as Scala lets you get to what you want, but it also shows why it's probably not a good idea to do what you're doing.
You can express (something close to) the type you want, but I'm not sure what you intend to gain. First, if you want to take different arglist types, then Column needs to be generic.
trait Column[-A] {
def rule(arg: A): String
}
Then we can implement your case objects as subclasses of an appropriate parameterization of this.
case object FirstColumn extends Column[String] {
def rule(arg: String): String =
"stub implementation"
}
case object SecondColumn extends Column[(String, String)] {
def rule(arg: (String, String)): String =
"stub implementation"
}
Note that FirstColumn and SecondColumn do not inherit from the same Column[A] as they don't implement the same method. We can get them to have a common type, but... not in a very useful way.
One option is to find a common supertype of Column[String] and Column[(String, String)], which (since the argument is contravariant) is akin to finding a common subtype of String and (String, String). The closest common subtype is... Null. That's not helpful unless you're only ever planning to pass null to your rule.
Instead, we can use existentials.
val foo: Column[_] = FirstColumn
val bar: Column[_] = SecondColumn
Now we've lost all type information. You can access the foo.rule slot and you can print it, but you can't call it because we don't know what we need to pass it. You'll have to do a cast to get it back to a usable format.
The point that I'm making here is that, yes, it's doable, but once you've lost as much type information as you're giving up, there's not much point. The type system is correctly telling us that foo and bar have virtually nothing in common except the existence of a method named rule which takes... some kind of argument. From a type theory perspective, it's hard to get more uninteresting than that.

Inheriting type parameter classes in Scala

I have one abstract class with type parameter and few its implementations:
abstract class AbstractClass[T] {
def func: T
}
class DoubleClass extends AbstractClass[Double]{
def func = 0.0
}
and then I want to create a function that takes some sequence of such objects:
def someFunc(objs: Iterable[AbstractClass]) = objs.foreach(obj=>println(obj.func))
but it says "Class AbstractClass takes type parameters"
I am new at scala and definitely doing something wrong, but i can`t figure out what
It should in most cases be def someFunc[A](objs: Iterable[AbstractClass[A]]). In particular, this allows return type to depend on A, e.g.
def someFunc[A](objs: Iterable[AbstractClass[A]]) = objs.map(_.func)
returns Iterable[A].
Sometimes you may actually want to allow mixing AbstractClasses with different parameters. E.g. in your example you just print func, which can always be done. In this case, as Sascha Kolberg's answer says, use a wildcard:
def someFunc(objs: Iterable[AbstractClass[_]])
But if you find yourself using wildcards constantly, consider rethinking your design.
The simple solution would be to add the wildcard type as type argument to AbstractClass in your function:
def someFunc(objs: Iterable[AbstractClass[_]]) = objs.foreach(obj=>println(obj.func))
This way objs can be an iterable containing any kind of AbstractClass, so essentially a mixed type collection.
If you want to be sure, that the iterable argument of someFunc holds only instances of one implementation of AbstractClass[_], you can add another type parameter to someFunc:
def someFunc[A <: AbstractClass[_]](objs: Iterable[A]) = objs.foreach(obj=>println(obj.func))
<: is a type bound that basically says that A is a subclass of AbstractClass[_]

implicit conversions that add properties to a type, rather than to an instance of a type

I was reading through some older Scala posts to better understand type classes, and I ran
across this one that seemed quite useful, but the example seems to have gotten stale.
Can someone help me figure out the correct way to do what Phillipe intended ? Here is the code
trait Default[T] { def value : T }
implicit object DefaultInt extends Default[Int] {
def value = 42
}
implicit def listsHaveDefault[T : Default] = new Default[List[T]] {
def value = implicitly[Default[T]].value :: Nil
}
default[List[List[Int]]]
When copy/pasted and run in REPL, i get this>
scala> default[List[List[Int]]]
<console>:18: error: not found: value default
default[List[List[Int]]]
^
This doesn't have anything to do with the Scala version. If you read #Philippe's answer, you will notice that the default method simply isn't defined anywhere. That will not work in any Scala version.
It should look something like this:
def default[T: Default] = implicitly[Default[T]].value
Thanks to Jorg for his answer, which, in conjunction with this blog post helped me figure out what is going on here. Hopefully my additional answer will help others who have been confused by this.
My mental picture of type classes is that they are a means by which an author of a library would imbue his/her
library with the desireable trait of retroactive extensibility.
On the other hand, there is yet another technique for ad hoc polymorphism: implicits with wrapper classes.
You would use this latter technique when you are the consumer of a library which has some type
which is missing methods that you find useful.
I am going to try to extend Phillipe's example a bit to illustrate my understanding of how
type classes could be used by a library designer. I am not that experienced with Scala... so if
anyone notices something that is not correct in my understanding please do correct me ! ;^)
// 'Default' defines a trait that represents the ability to manufacture
// defaults for a particular type 'T'.
//
trait Default[T] { def value : T }
// Define a default for int.. this is an object default
//
implicit object DefaultInt extends Default[Int] {
def value = 42
}
// Define a default for Lists that contain instances of a 'T'.
// Interesting that this is method, not an object implicit definition. I
// guess that is to enable the 'on the fly' creation of default values for
// lists of any old type.... So I guess that's why we have
// a 'method implicit' rather than an 'object implicit' definition.
implicit def listsHaveDefault[T : Default] = new Default[List[T]] {
def value = implicitly[Default[T]].value :: Nil
}
// Here is the meat of the library... a method to make a message based of
// some arbitrary seed String, where that method is parameterized by 'T',
// a type chosen by the library user. That 'T' can be
// types for which implicits are already defined by the base library
// (T = Int, and List[T]), or an implicit defined by the library user.
//
// So the library is open for extension.
//
def makeMsg[T](msg: String)(implicit something: Default[T]) : String = {
msg + something.value
}
Given the above code, if I can create a message for the type List[List[Int]], or for Int's
makeMsg[List[List[Int]]]("moocow-")
makeMsg[Int]("dogbox")
And I get this result:
res0: String = moocow-List(List(42))
res1: String = dogbox42
If I want to override the default implicit value for a given type, I can do so like this:
makeMsg[Int]("moocow-")(something=new Object with Default[Int] { def value = 33344 } )
And I get this result:
res3: String = moocow-33344

Scala: Type parameters and inheritance

I'm seeing something I do not understand. I have a hierarchy of (say) Vehicles, a corresponding hierarchy of VehicalReaders, and a VehicleReader object with apply methods:
abstract class VehicleReader[T <: Vehicle] {
...
object VehicleReader {
def apply[T <: Vehicle](vehicleId: Int): VehicleReader[T] = apply(vehicleType(vehicleId))
def apply[T <: Vehicle](vehicleType VehicleType): VehicleReader[T] = vehicleType match {
case VehicleType.Car => new CarReader().asInstanceOf[VehicleReader[T]]
...
Note that when you have more than one apply method, you must specify the return type. I have no issues when there is no need to specify the return type.
The cast (.asInstanceOf[VehicleReader[T]]) is the reason for the question - without it the result is compile errors like:
type mismatch;
found : CarReader
required: VehicleReader[T]
case VehicleType.Car => new CarReader()
^
Related questions:
Why cannot the compiler see a CarReader as a VehicleReader[T]?
What is the proper type parameter and return type to use in this situation?
I suspect the root cause here is that VehicleReader is invariant on its type parameter, but making it covariant does not change the result.
I feel like this should be rather simple (i.e., this is easy to accomplish in Java with wildcards).
The problem has a very simple cause and really doesn't have anything to do with variance. Consider even more simple example:
object Example {
def gimmeAListOf[T]: List[T] = List[Int](10)
}
This snippet captures the main idea of your code. But it is incorrect:
val list = Example.gimmeAListOf[String]
What will be the type of list? We asked gimmeAListOf method specifically for List[String], however, it always returns List[Int](10). Clearly, this is an error.
So, to put it in words, when the method has a signature like method[T]: Example[T] it really declares: "for any type T you give me I will return an instance of Example[T]". Such types are sometimes called 'universally quantified', or simply 'universal'.
However, this is not your case: your function returns specific instances of VehicleReader[T] depending on the value of its parameter, e.g. CarReader (which, I presume, extends VehicleReader[Car]). Suppose I wrote something like:
class House extends Vehicle
val reader = VehicleReader[House](VehicleType.Car)
val house: House = reader.read() // Assuming there is a method VehicleReader[T].read(): T
The compiler will happily compile this, but I will get ClassCastException when this code is executed.
There are two possible fixes for this situation available. First, you can use existential (or existentially quantified) type, which can be though as a more powerful version of Java wildcards:
def apply(vehicleType: VehicleType): VehicleReader[_] = ...
Signature for this function basically reads "you give me a VehicleType and I return to you an instance of VehicleReader for some type". You will have an object of type VehicleReader[_]; you cannot say anything about type of its parameter except that this type exists, that's why such types are called existential.
def apply(vehicleType: VehicleType): VehicleReader[T] forSome {type T} = ...
This is an equivalent definition and it is probably more clear from it why these types have such properties - T type is hidden inside parameter, so you don't know anything about it but that it does exist.
But due to this property of existentials you cannot really obtain any information about real type parameters. You cannot get, say, VehicleReader[Car] out of VehicleReader[_] except via direct cast with asInstanceOf, which is dangerous, unless you store a TypeTag/ClassTag for type parameter in VehicleReader and check it before the cast. This is sometimes (in fact, most of time) unwieldy.
That's where the second option comes to the rescue. There is a clear correspondence between VehicleType and VehicleReader[T] in your code, i.e. when you have specific instance of VehicleType you definitely know concrete T in VehicleReader[T] signature:
VehicleType.Car -> CarReader (<: VehicleReader[Car])
VehicleType.Truck -> TruckReader (<: VehicleReader[Truck])
and so on.
Because of this it makes sense to add type parameter to VehicleType. In this case your method will look like
def apply[T <: Vehicle](vehicleType: VehicleType[T]): VehicleReader[T] = ...
Now input type and output type are directly connected, and the user of this method will be forced to provide a correct instance of VehicleType[T] for that T he wants. This rules out the runtime error I have mentioned earlier.
You will still need asInstanceOf cast though. To avoid casting completely you will have to move VehicleReader instantiation code (e.g. yours new CarReader()) to VehicleType, because the only place where you know real value of VehicleType[T] type parameter is where instances of this type are constructed:
sealed trait VehicleType[T <: Vehicle] {
def newReader: VehicleReader[T]
}
object VehicleType {
case object Car extends VehicleType[Car] {
def newReader = new CarReader
}
// ... and so on
}
Then VehicleReader factory method will then look very clean and be completely typesafe:
object VehicleReader {
def apply[T <: Vehicle](vehicleType: VehicleType[T]) = vehicleType.newReader
}