No Implicit arguments of Type: Any - scala

I followed this article to create union types. The articles has few answers about the Primitive type but my scenario is an extension to it.
So, I am trying to define a method which takes Map[String, A] where A is the set of allowed type.
This is my class of union types:
sealed trait SupportedType[A]
object SupportedType {
implicit val byteBufferColumn : SupportedType[ByteBuffer] = new SupportedType[ByteBuffer] {}
implicit val longColumn : SupportedType[java.lang.Long] = new SupportedType[java.lang.Long] {}
implicit val byteArrayColumn : SupportedType[Array[Byte]] = new SupportedType[Array[Byte]] {}
implicit val stringColumn : SupportedType[String] = new SupportedType[String] {}
}
This is my method I defined:
def upsert[A: SupportedType](key: T, values: Map[String, A], timestamp: Long, ttl: Duration): Future[Unit]
This is how I am calling the method:
dataStore.upsert(
cacheKey,
Map(
itColumn -> ByteBuffer.wrap(Utils.compress(iti.toByteArray)),
cacheWriteTimeColumn -> writeTime.toEpochMilli
),
writeTime.toEpochMilli,
ttl
)
error: No implicit arguments of type: SupportedType[Any]
My guess is writeTime.toEpochMilli returns java.long type and as you can see in SupportedType, I tried to define java.lang.Long but thats not working.
Any help would be appreciated.

You can use the magnet pattern in combination to a typeclass like this:
import scala.language.implicitConversions
trait ColumnValue {
def serialize(): String
}
object ColumnValue {
trait SupportedType[A] {
def toColumn(a: A): ColumnValue
}
object SupportedType {
implicit final val stringSupportedType: SupportedType[String] =
new SupportedType[String] {
override def toColumn(str: String): ColumnValue =
new ColumnValue {
override def serialize(): String =
"\"" + str + "\""
}
}
implicit final val intSupportedType: SupportedType[Int] =
new SupportedType[Int] {
override def toColumn(int: Int): ColumnValue =
new ColumnValue {
override def serialize(): String =
int.toString
}
}
implicit final val booleanSupportedType: SupportedType[Boolean] =
new SupportedType[Boolean] {
override def toColumn(bool: Boolean): ColumnValue =
new ColumnValue {
override def serialize(): String =
if (bool) "1" else "0"
}
}
implicit final def listSupportedType[A](implicit ev: SupportedType[A]): SupportedType[List[A]] =
new SupportedType[List[A]] {
override def toColumn(list: List[A]): ColumnValue =
new ColumnValue {
override def serialize(): String =
list.map(a => ev.toColumn(a).serialize()).mkString("[", ",", "]")
}
}
}
def apply[A](a: A)(implicit ev: SupportedType[A]): ColumnValue =
ev.toColumn(a)
implicit def supportedType2Column[A : SupportedType](a: A): ColumnValue =
apply(a)
}
You may create some helper functions to reduce some of the boilerplate.
Which can be used like this:
final case class Table(data: Map[String, ColumnValue]) {
def upsert(values: Map[String, ColumnValue]): Table =
copy(this.data ++ values)
}
object Table {
val empty: Table =
Table(data = Map.empty)
}
val result = Table.empty.upsert(Map(
"a" -> "foo",
"b" -> 10,
"c" -> List(true, false, true)
))
See the code running here.

Related

In Scala, how to deal with heterogeneous list of the same parameterized type

I have an array of Any (in real life, it's a Spark Row, but it's sufficient to isolate the problem)
object Row {
val buffer : Array[Any] = Array(42, 21, true)
}
And I want to apply some operations on its elements.
So, I've defined a simple ADT to define a compute operation on a type A
trait Op[A] {
def cast(a: Any) : A = a.asInstanceOf[A]
def compute(a: A) : A
}
case object Count extends Op[Int] {
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op[Boolean] {
override def compute(a: Boolean): Boolean = a
}
Given that I have a list of all operations and I know which operation is to apply to each element, let's use these operations.
object GenericsOp {
import Row._
val ops = Seq(Count, Exist)
def compute() = {
buffer(0) = ops(0).compute(ops(0).cast(buffer(0)))
buffer(1) = ops(0).compute(ops(0).cast(buffer(1)))
buffer(2) = ops(1).compute(ops(1).cast(buffer(2)))
}
}
By design, for a given op, types are aligned between cast and combine. But unfortunately the following code does not compile. The error is
Type mismatch, expected: _$1, actual: AnyVal
Is there a way to make it work ?
I've found a workaround by using abstract type member instead of type parameter.
object AbstractOp extends App {
import Row._
trait Op {
type A
def compute(a: A) : A
}
case object Count extends Op {
type A = Int
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op {
type A = Boolean
override def compute(a: Boolean): Boolean = a
}
val ops = Seq(Count, Exist)
def compute() = {
val op0 = ops(0)
val op1 = ops(1)
buffer(0) = ops(0).compute(buffer(0).asInstanceOf[op0.A])
buffer(1) = ops(0).compute(buffer(1).asInstanceOf[op0.A])
buffer(2) = ops(1).compute(buffer(2).asInstanceOf[op1.A])
}
}
Is there a better way ?
It seems that your code can be simplified by making Op[A] extend Any => A:
trait Op[A] extends (Any => A) {
def cast(a: Any) : A = a.asInstanceOf[A]
def compute(a: A) : A
def apply(a: Any): A = compute(cast(a))
}
case object Count extends Op[Int] {
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op[Boolean] {
override def compute(a: Boolean): Boolean = a
}
object AbstractOp {
val buffer: Array[Any] = Array(42, 21, true)
val ops: Array[Op[_]] = Array(Count, Count, Exist)
def main(args: Array[String]): Unit = {
for (i <- 0 until buffer.size) {
buffer(i) = ops(i)(buffer(i))
}
println(buffer.mkString("[", ",", "]"))
}
}
Since it's asInstanceOf everywhere anyway, it does not make the code any less safe than what you had previously.
Update
If you cannot change the Op interface, then invoking cast and compute is a bit more cumbersome, but still possible:
trait Op[A] {
def cast(a: Any) : A = a.asInstanceOf[A]
def compute(a: A) : A
}
case object Count extends Op[Int] {
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op[Boolean] {
override def compute(a: Boolean): Boolean = a
}
object AbstractOp {
val buffer: Array[Any] = Array(42, 21, true)
val ops: Array[Op[_]] = Array(Count, Count, Exist)
def main(args: Array[String]): Unit = {
for (i <- 0 until buffer.size) {
buffer(i) = ops(i) match {
case op: Op[t] => op.compute(op.cast(buffer(i)))
}
}
println(buffer.mkString("[", ",", "]"))
}
}
Note the ops(i) match { case op: Opt[t] => ... } part with a type-parameter in the pattern: this allows us to make sure that cast returns a t that is accepted by compute.
As a more general solution than Andrey Tyukin's, you can define the method outside Op, so it works even if Op can't be modified:
def apply[A](op: Op[A], x: Any) = op.compute(op.cast(x))
buffer(0) = apply(ops(0), buffer(0))

Type parameters and inheritance in Scala

Is there a simple way to return a concrete type in an override method? And what about creating an instance of a concrete implementation? And calling chained methods implemented in the concrete class, so they return a correct type, too? I have a solution (based on https://stackoverflow.com/a/14905650) but I feel these things should be simpler.
There are many similar questions, but everyone's case is a little different, so here is another example (shortened from https://github.com/valdanylchuk/saiml/tree/master/src/main/scala/saiml/ga). When replying, if possible, please check if the whole code block compiles with your suggested change, because there are subtle cascading effects. I could not make this work with the "curiously recurring template pattern", for example (not that I find it nicer).
import scala.reflect.ClassTag
import scala.util.Random
abstract class Individual(val genome: String) {
type Self
def this() = this("") // please override with a random constructor
def crossover(that: Individual): Self
}
class HelloGenetic(override val genome: String) extends Individual {
type Self = HelloGenetic
def this() = this(Random.alphanumeric.take("Hello, World!".length).mkString)
override def crossover(that: Individual): HelloGenetic = {
val newGenome = this.genome.substring(0, 6) + that.genome.substring(6)
new HelloGenetic(newGenome)
}
}
class Population[A <: Individual {type Self = A} :ClassTag]( val size: Int,
tournamentSize: Int, givenIndividuals: Option[Vector[A]] = None) {
val individuals: Vector[A] = givenIndividuals getOrElse
Vector.tabulate(size)(_ => implicitly[ClassTag[A]].runtimeClass.newInstance.asInstanceOf[A])
def tournamentSelect(): A = individuals.head // not really, skipped
def evolve: Population[A] = {
val nextGen = (0 until size).map { _ =>
val parent1: A = tournamentSelect()
val parent2: A = tournamentSelect()
val child: A = parent1.crossover(parent2)
child
}.toVector
new Population(size, tournamentSize, Some(nextGen))
}
}
class Genetic[A <: Individual {type Self = A} :ClassTag](populationSize: Int, tournamentSize: Int) {
def optimize(maxGen: Int, maxMillis: Long): Individual = {
val first = new Population[A](populationSize, tournamentSize)
val optPop = (0 until maxGen).foldLeft(first) { (pop, _) => pop.evolve }
optPop.individuals.head
}
}
The CRTP version is
abstract class Individual[A <: Individual[A]](val genome: String) {
def this() = this("") // please override with a random constructor
def crossover(that: A): A
}
class HelloGenetic(override val genome: String) extends Individual[HelloGenetic] {
def this() = this(Random.alphanumeric.take("Hello, World!".length).mkString)
override def crossover(that: HelloGenetic): HelloGenetic = {
val newGenome = this.genome.substring(0, 6) + that.genome.substring(6)
new HelloGenetic(newGenome)
}
}
class Population[A <: Individual[A] :ClassTag]( val size: Int,
tournamentSize: Int, givenIndividuals: Option[Vector[A]] = None) {
val individuals: Vector[A] = givenIndividuals getOrElse
Vector.tabulate(size)(_ => implicitly[ClassTag[A]].runtimeClass.newInstance.asInstanceOf[A])
def tournamentSelect(): A = individuals.head // not really, skipped
def evolve: Population[A] = {
val nextGen = (0 until size).map { _ =>
val parent1: A = tournamentSelect()
val parent2: A = tournamentSelect()
val child: A = parent1.crossover(parent2)
child
}.toVector
new Population(size, tournamentSize, Some(nextGen))
}
}
class Genetic[A <: Individual[A] :ClassTag](populationSize: Int, tournamentSize: Int) {
def optimize(maxGen: Int, maxMillis: Long): Individual[A] = {
val first = new Population[A](populationSize, tournamentSize)
val optPop = (0 until maxGen).foldLeft(first) { (pop, _) => pop.evolve }
optPop.individuals.head
}
}
which compiles. For creating the instances, I'd suggest just passing functions:
class Population[A <: Individual[A]](val size: Int,
tournamentSize: Int, makeIndividual: () => A, givenIndividuals: Option[Vector[A]] = None) {
val individuals: Vector[A] = givenIndividuals getOrElse
Vector.fill(size)(makeIndividual())
...
}
If you want to pass them implicitly, you can easily do so:
trait IndividualFactory[A] {
def apply(): A
}
class HelloGenetic ... // remove def this()
object HelloGenetic {
implicit val factory: IndividualFactory[HelloGenetic] = new IndividualFactory[HelloGenetic] {
def apply() = new HelloGenetic(Random.alphanumeric.take("Hello, World!".length).mkString)
}
}
class Population[A <: Individual[A]](val size: Int,
tournamentSize: Int, givenIndividuals: Option[Vector[A]] = None)
(implicit factory: IndividualFactory[A]) {
val individuals: Vector[A] = givenIndividuals getOrElse
Vector.fill(size)(factory())
...
}

Apply a function to an object with generic type in Scala

I have this code
import scala.reflect.ClassTag
case class Data[T: ClassTag](list: List[T]) {
}
trait Transformation {
type T
type U
def transform(data: Data[T]) : Data[U]
}
class FromInt2String extends Transformation {
override type T = Int
override type U = String
override def transform(data: Data[T]) = new Data(List("1", "2", "3"))
}
class FromString2Int extends Transformation {
override type T = String
override type U = Int
override def transform(data: Data[T]) = new Data(List(1, 2, 3))
}
object Test extends App {
override def main(args: Array[String]) {
val data = new Data(List(1, 2, 3))
val int2String = new FromInt2String()
val data2 = int2String.transform(data)
val string2Int = new FromString2Int()
val data3 = string2Int.transform(data2)
val transformations = List(int2String, string2Int)
val data4 = transformations.foldLeft(data)((data, transformation) => {
transformation.transform(data)
})
}
}
The problem is in the foldLeft method. I can't do it because the type isn't compatible but I need to apply all the transforms in my initial object data
Any ideas how to do it?
Thanks
I've solved it using shapeless and this post
import scala.reflect.ClassTag
import shapeless._
object andThen extends Poly2 {
implicit def functions[A, B, C] = at[A => B, B => C](_ andThen _)
}
case class Data[T: ClassTag](list: List[T]) {
}
trait Transformation {
type T
type U
def transform(data: Data[T]) : Data[U]
}
class FromInt2String extends Transformation {
override type T = Int
override type U = String
override def transform(data: Data[T]) = new Data(List("1s", "2s", "3s"))
}
class FromString2Int extends Transformation {
override type T = String
override type U = Int
override def transform(data: Data[T]) = new Data(List(4, 5, 6))
}
object Test extends App {
override def main(args: Array[String]) {
val data = new Data(List(1, 2, 3))
println(data)
val int2String = new FromInt2String()
val data2 = int2String.transform(data)
println(data2)
val string2Int = new FromString2Int()
val data3 = string2Int.transform(data2)
println(data3)
val transformations = int2String.transform _ :: string2Int.transform _ :: HNil
val functions = transformations.reduceLeft(andThen)
val data4 = functions(data)
println(data4)
}
}
Thanks to all of you that help me

Scala HashMap with typed entries

I'm not sure if i got the topic right. I'll try to describe the problem.
I have one common field trait. StringField and IntField extend this class:
trait BaseField[T] {
def name = "field"
var owner : FieldContainer
var value : T
def set(value : T) {
this.value = value
this.owner.fields.put(name, this)
}
}
class StringField extends BaseField[String]
class IntField extends BaseField[Int]
How do i implement the FieldContainer class? What i want is to match the FieldTypes later on:
val fieldContainer = {...init code here...}
fieldContainer.fields foreach {
field -> {
field match {
case f: StringField => println("String")
case f: IntField => println("Int")
case _ => println("Unknown")
}
}
}
This is my FieldContainer (so far)
trait FieldContainer {
private metaFields : HashMap[String, Any] = new HashMap[String, Any]
def fields : HashMap[String, Any] = this.metaFields
}
And i use it in that way:
class Pizza extends FieldContainer {
object name extends StringField(this) {
override def name = "pizza_name"
}
object pieces extends IntField(this) {
override def name = "pieces_count"
}
}
Fields don't need to know their owners.
class BaseField[T](initValue: T, val name: String = "field") {
private[this] var _value: T = initValue
def apply() = _value
def update(v: T) { _value = v }
override def toString(): String = name + "(" + apply() + ")"
}
class StringField(initValue: String, name: String = "field") extends BaseField[String](initValue, name)
class IntField(initValue: Int, name: String = "field") extends BaseField[Int](initValue, name)
trait FieldContainer {
protected def addField[C <: BaseField[_]](field: C): C = {
_fields += (field.name -> field)
field
}
protected def stringField(initValue: String, name: String): StringField =
addField(new StringField(initValue, name))
protected def intField(initValue: Int, name: String): IntField =
addField(new IntField(initValue, name))
private var _fields : Map[String, Any] = Map[String, Any]()
def fields : Map[String, Any] = _fields
}
Objects (singletons) initialized when first accessed, so you should use val instead of object for fields:
class Pizza extends FieldContainer {
val name = stringField("", "pizza_name")
val pieces = intField(0, "pieces_count")
val mass: BaseField[Double] = addField(new BaseField[Double](0, "mass"))
}
Usage:
scala> val p = new Pizza()
p: Pizza = Pizza#8c61644
scala> p.fields
res0: Map[String,Any] = Map(pizza_name -> pizza_name(), pieces_count -> pieces_count(0), mass -> mass(0.0))
scala> p.name() = "new name"
scala> p.pieces() = 10
scala> p.mass() = 0.5
scala> p.fields
res4: Map[String,Any] = Map(pizza_name -> pizza_name(new name), pieces_count -> pieces_count(10), mass -> mass(0.5))
scala> p.name()
res5: String = new name
scala> p.pieces()
res6: Int = 10
scala> p.mass
res7: BaseField[Double] = mass(0.5)

Define a MongoRecord in Lift with a Map inside it

I cannot find the way to define a MongoRecord with a Map[String,String] field inside it in Lift - MongoRecord.
The Lift documentation says:
All standard Record Fields are supported. There is also support for Mongo specific types; ObjectId, UUID, Pattern, List, and Map.
How can I define Map and List fields?
I defined a BsonRecordMapField:
class BsonRecordMapField[OwnerType <: BsonRecord[OwnerType], SubRecordType <: BsonRecord[SubRecordType]]
(rec: OwnerType, valueMeta: BsonMetaRecord[SubRecordType])(implicit mf: Manifest[SubRecordType])
extends MongoMapField[OwnerType, SubRecordType](rec: OwnerType) {
import scala.collection.JavaConversions._
override def asDBObject: DBObject = {
val javaMap = new HashMap[String, DBObject]()
for ((key, element) <- value) {
javaMap.put(key.asInstanceOf[String], element.asDBObject)
}
val dbl = new BasicDBObject(javaMap)
dbl
}
override def setFromDBObject(dbo: DBObject): Box[Map[String, SubRecordType]] = {
val mapResult: Map[String, SubRecordType] = (for ((key, dboEl) <- dbo.toMap.toSeq) yield (key.asInstanceOf[String], valueMeta.fromDBObject(dboEl.asInstanceOf[DBObject]))).toMap
setBox(Full(mapResult))
}
override def asJValue = {
val fieldList = (for ((key, elem) <- value) yield JField(key, elem.asJValue)).toList
JObject(fieldList)
}
override def setFromJValue(jvalue: JValue) = jvalue match {
case JNothing | JNull if optional_? => setBox(Empty)
case JObject(fieldList) => val retrievedMap = fieldList.map {
field =>
val key = field.name
val valRetrieved = valueMeta.fromJValue(field.value) openOr valueMeta.createRecord
(key, valRetrieved)
}.toMap
setBox(Full(retrievedMap))
case other => setBox(FieldHelpers.expectedA("JObject", other))
}
}
This is the implicit query for Rogue:
class BsonRecordMapQueryField[M <: BsonRecord[M], B <: BsonRecord[B]](val field: BsonRecordMapField[M, B])(implicit mf: Manifest[B]) {
def at(key: String): BsonRecordField[M, B] = {
val listBox = field.setFromJValue(JObject(List(JField("notExisting", JInt(0)))))
val rec = listBox.open_!.head._2
new BsonRecordField[M, B](field.owner, rec.meta)(mf) {
override def name = field.name + "." + key
}
}
}
object ExtendedRogue extends Rogue {
implicit def bsonRecordMapFieldToBsonRecordMapQueryField[M <: BsonRecord[M], B <: BsonRecord[B]](f: BsonRecordMapField[M, B])(implicit mf: Manifest[B]): BsonRecordMapQueryField[M, B] = new BsonRecordMapQueryField[M, B](f) (mf)
}
You can use the at operator in map now.
What about MongoMapField?