Overloading methods based on generics - scala

I'd like to overload a method based on generics - so something like this:
case class Indexed2dArr[Dim0Type, Dim1Type] (
indices: (List[Dim0Type], List[Dim1Type]),
array: List[List[Float]],
) {
def getSliceAtIndexLocation(i: Dim0Type): (List[Dim1Type], List[Float]) = ???
def getSliceAtIndexLocation(i: Dim1Type): (List[Dim0Type], List[Float]) = ???
}
So if getSliceAtIndexLocation is called with a parameter of Dim0Type, it returns a single-dimensioned slice of the orginal array, with an index of Dim1Type. And vice-versa for calling with Dim1Type.
This raises a double definition compiler error - that the two methods have the same type after type erasure, this type being (i: Object): Tuple2. Is there a valid way to wrangle this or is it straight-up impossible?

Try either DummyImplicit
case class Indexed2dArr[Dim0Type, Dim1Type] (
indices: (List[Dim0Type], List[Dim1Type]),
array: List[List[Float]],
) {
def getSliceAtIndexLocation(i: Dim0Type): (List[Dim1Type], List[Float]) = ???
def getSliceAtIndexLocation(i: Dim1Type)(implicit
di: DummyImplicit): (List[Dim0Type], List[Float]) = ???
}
or type class pattern
case class Indexed2dArr[Dim0Type, Dim1Type] (
indices: (List[Dim0Type], List[Dim1Type]),
array: List[List[Float]],
) {
def getSliceAtIndexLocation[A](i: A)(implicit tc: TC[A]): tc.Out = tc(i)
trait TC[A] {
type B
type Out = TC.MkOut[B]
def apply(i: A): Out
}
object TC {
type MkOut[B] = (List[B], List[Float])
type Aux[A, B0] = TC[A] { type B = B0 }
def instance[A, B0](f: A => MkOut[B0]): Aux[A, B0] = new TC[A] {
override type B = B0
override def apply(i: A): Out = f(i)
}
implicit val dim0Type: Aux[Dim0Type, Dim1Type] = instance(i => ???)
implicit val dim1Type: Aux[Dim1Type, Dim0Type] = instance(i => ???)
}
}
or magnet pattern
import scala.language.implicitConversions
case class Indexed2dArr[Dim0Type, Dim1Type] (
indices: (List[Dim0Type], List[Dim1Type]),
array: List[List[Float]],
) {
def getSliceAtIndexLocation(m: Magnet): m.Out = m()
trait Magnet {
type B
type Out = Magnet.MkOut[B]
def apply(): Out
}
object Magnet {
type MkOut[B] = (List[B], List[Float])
type Aux[B0] = Magnet { type B = B0 }
def instance[B0](x: MkOut[B0]): Aux[B0] = new Magnet {
override type B = B0
override def apply(): Out = x
}
implicit def dim0Type(i: Dim0Type): Aux[Dim1Type] = instance(???)
implicit def dim1Type(i: Dim1Type): Aux[Dim0Type] = instance(???)
}
}

Related

Scala Method on Generic Data Type

I am trying to create a generic class that only accepts java.math.BigDecimal or Long. Here is the code:
class myClass[T]()
{
def display( x : T) = {
println(x.doubleValue())
}
}
val input = new java.math.BigDecimal(100)
// val input = 100L
val x = new myClass[java.math.BigDecimal]()
x.display(input)
Clearly I will have this error: ScalaFiddle.scala:22: error: value doubleValue is not a member of type parameter T.
I tried playing with implicit conversion, view bound, and context bound for hours. No result so far. Is there any way I can force Scala to believe me that T has method .doubleValue()? (java.big.Decimal and Long both has .doubleValue() method, but they don't share same super-class)
Try structural type bound
class myClass[T <: {def doubleValue(): Double}]
or type class
trait HasDoubleValue[T] {
def doubleValue(t: T): Double
}
object HasDoubleValue {
implicit val long: HasDoubleValue[Long] = t => t.doubleValue
implicit val bigDecimal: HasDoubleValue[BigDecimal] = t => t.doubleValue
}
implicit class DoubleValueOps[T: HasDoubleValue](x: T) {
def doubleValue(): Double = implicitly[HasDoubleValue[T]].doubleValue(x)
}
class myClass[T: HasDoubleValue]
In Dotty (Scala 3) we might use union types, for example,
class myClass[T <: (Long | java.math.BigDecimal)]() {
def display(x: T) =
println(
x match {
case t: Long => t.doubleValue
case t: java.math.BigDecimal => t.doubleValue
}
)
}
new myClass().display(new java.math.BigDecimal(100)) // OK
new myClass().display(100L) // OK
new myClass().display("100") // Error
scala> class C private (n: Number) {
| def this(i: Long) = this(i: Number)
| def this(b: BigDecimal) = this(b: Number)
| def d = n.doubleValue
| }
defined class C
scala> new C(42L).d
res0: Double = 42.0
scala> new C(BigDecimal("123456789")).d
res1: Double = 1.23456789E8
or with a type parameter
scala> class C[A <: Number] private (n: A) { def d = n.doubleValue ; def a = n } ; object C {
| def apply(i: Long) = new C(i: Number) ; def apply(b: BigDecimal) = new C(b) }
defined class C
defined object C

How to pattern match all classes with context bound

I have a type class and a few instances:
trait TC[T] { def doThings(x: T): Unit }
implicit val tcA = new TC[A] { /* ... */}
implicit val tcB = new TC[B] { /* ... */}
implicit val tcC = new TC[C] { /* ... */}
/* ... */
In my call site, I have input as Any, and I need to check if there is an implicit for the input actual type:
def process(in: Any) = in match {
case x: A => implicitly[TC[A]].doThings(x)
case x: B => implicitly[TC[B]].doThings(x)
case x: C => implicitly[TC[C]].doThings(x)
//...
}
This seems tedious and unnecessary, as I have to list all the classes that have this type class instance. Can I achieve this by something like:
def process(in: Any) = in match {
case x: T : TC => implicitly[TC[T]].doThings(x) //This does not work
}
Edit: input is an Any (an Object from a Java library). Cannot use generic or context bound on the input.
If you really want to do what you have mentioned in your question, you can write it as below, but if you just want to call doThings by finding an implicit instance of appropriate TC - refer João Guitana answer
object Main extends App {
class A
class B
class C
trait TC[T] { def doThings(x: T): Unit }
implicit val tcA = new TC[A] {
override def doThings(x: A): Unit = println("From A")
}
implicit val tcB = new TC[B] {
override def doThings(x: B): Unit = println("From B")
}
implicit val tcC = new TC[C] {
override def doThings(x: C): Unit = println("From C")
}
def process[T: ClassTag](in: T) = in match {
case x: A => implicitly[TC[A]].doThings(x)
case x: B => implicitly[TC[B]].doThings(x)
case x: C => implicitly[TC[C]].doThings(x)
}
process(new A())
process(new B())
process(new C())
}
/* === Output ====
From A
From B
From C
*/
You need to ask for an implicit TC, Any won't work. As follows:
trait TC[T] { def doThings(x: T): Unit }
implicit def tcS: TC[String] = new TC[String] {
override def doThings(x: String): Unit = println("string")
}
implicit def tcI: TC[Int] = new TC[Int] {
override def doThings(x: Int): Unit = println("int")
}
def process[T : TC](x: T): Unit = implicitly[TC[T]].doThings(x)
process("")
process(1)
// process(4L) wont compile
Try it out!

How instantiate case class from Map[String, String]

Lets say I have
case class Sample(i:Int, b:Boolean)
and
Map[String, String]("i" => "1", "b" => "false")
What is most concise way to instantiate any case class(if all fields are in map), signature like this:
get[T](map:[String, String]) : T
Probably shapeless can help acomplish this task, but I am almost unfamiliar with it. Thanks!
Firstly you can transform Map[String, String] into Map[Symbol, Any] and then use type classes shapeless.ops.maps.FromMap (or extention method .toRecord) and LabelledGeneric:
import shapeless.LabelledGeneric
import shapeless.record.Record
import shapeless.syntax.std.maps._
case class Sample(i: Int, b: Boolean)
val rec = Map('i -> 1, 'b -> false).toRecord[Record.`'i -> Int, 'b -> Boolean`.T].get
LabelledGeneric[Sample].from(rec) //Sample(1,false)
If not using Shapeless is an option for you, you could do it in a simple way without it. Here is a sample implementation where I use the Try Monad and a pattern matching to transform the Map into your case class:
(Try("1".toInt), Try("false".toBoolean)) match {
case (Success(intVal), Success(boolVal)) =>
Sample(intVal, boolVal)
case _ => // Log and ignore the values
}
Of course this is a bit verbose than the Shapeless version, but if you do not want to use a full library just for this simple use case, you could always do it using Scala library!
guys. Probably I wasn't too concise. What I really need is Generic parser from Map of Strings to case class. Thanks for pointing out to LabelledGeneric. Here is solution:
import shapeless.labelled.{FieldType, field}
import shapeless.{::, HList, HNil, LabelledGeneric, Lazy, Witness}
object FieldParser {
trait ValParser[A] {
def parse(str:String): A
}
trait FieldParser[A] {
def parse: A
}
type FT[A, B] = FieldType[A, B]
type ListField[K <: Symbol, A] = FieldType[K, List[A]]
type FP[A] = FieldParser[A]
type Args = (List[String],Map[String, Int])
type Named[K <: Symbol] = Witness.Aux[K]
private def create[A](thunk: A): FP[A] = {
new FP[A] {
def parse: A = thunk
}
}
def apply[A](implicit st: Lazy[FP[A]]): FP[A] = st.value
implicit def genericParser[A, R <: HList](implicit generic: LabelledGeneric.Aux[A, R], parser: Lazy[FP[R]], args:Args): FP[A] = {
create(generic.from(parser.value.parse))
}
implicit def hlistParser[K <: Symbol, H, T <: HList](implicit hParser: Lazy[FP[FT[K, H]]], tParser: FP[T]): FP[FT[K, H] :: T] = {
create {
val hv = hParser.value.parse
val tv = tParser.parse
hv :: tv
}
}
implicit def standardTypeParser[K <: Symbol, V:ValParser](implicit named: Named[K], args:Args): FP[FieldType[K, V]] = {
create(field[K](implicitly[ValParser[V]].parse(findArg)))
}
implicit def optionParser[V](implicit valParser:ValParser[V]): ValParser[Option[V]] = new ValParser[Option[V]]{
def parse(str:String):Option[V] = {
str.isEmpty match {
case true => None
case false => Some(valParser.parse(str))
}
}
}
implicit def listParser[V](implicit valParser:ValParser[V]): ValParser[List[V]] = new ValParser[List[V]]{
def parse(str:String):List[V] = {
str.isEmpty match {
case true => Nil
case false => str.split(",").map(valParser.parse).toList
}
}
}
implicit def doubleParser: ValParser[Double] = new ValParser[Double]{
def parse(str:String):Double = str.toDouble
}
implicit def intParser: ValParser[Int] = new ValParser[Int]{
def parse(str:String):Int = str.toInt
}
implicit def strParser: ValParser[String] = new ValParser[String]{
def parse(str:String):String = str
}
implicit def boolParser: ValParser[Boolean] = new ValParser[Boolean]{
def parse(str:String):Boolean = str.toBoolean
}
implicit val hnilParser: FP[HNil] = create(HNil)
private def findArg[K <: Symbol](implicit args:Args, named: Named[K]): String = {
val name = named.value.name
val index = args._2(name)
args._1(index)
}
}

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())
...
}

Hoes do Spray Parameters work?

I'm trying to wrap my head around how Spray has implemented their Directives, and in particular the Parameter extraction DSL.
I understand the magnet pattern (barely) but am stuck on how the ParamDefMagnet and ParamDefMagnet2 work together.
def parameter(pdm: ParamDefMagnet): pdm.Out = pdm()
trait ParamDefMagnet {
type Out
def apply(): Out
}
trait ParamDefMagnet2[T] {
type Out
def apply(value: T): Out
}
type ParamDefMagnetAux[A, B] = ParamDefMagnet2[A] { type Out = B }
def ParamDefMagnetAux[A, B](f: A ⇒ B) = new ParamDefMagnet2[A] { type Out = B; def apply(value: A) = f(value) }
I'm trying to work out how a ParamDefManget2 is implicitly converted to a ParamDefMagnet by the the below implicit method.
object ParamDefMagnet {
implicit def apply[T](value: T)(implicit pdm2: ParamDefMagnet2[T]) = new ParamDefMagnet {
type Out = pdm2.Out
def apply() = pdm2(value)
}
}
If i call parameter("name"), how is "name" implicitly converted to a ParamDefMagnet? And if it converts it to a ParamDefMagnet2 first, then where does value: T come from in order to convert it to a ParamDefMagnet?
So after digging around with examples, I think i've finally got to the bottom of how the parameter function works:
def parameter(pdm: ParamDefMagnet): pdm.Out = pdm()
An example for extracting a parameter of type String:
val p: Directive1[String] = parameter("name")
// we can then apply the function with the extracted name
p { name =>
// stuff
}
Spray uses a bunch of implicit conversions but basically, if you have a String and a String => Directive1[String], you can construct a () => Directive1[String]:
// Our String => Directive1[String]
val pdm2: ParamDefMagnet2[String] { type Out = Directive1[String] } = ParamDefMagnet2.fromString
// Our () => Directive1[String]
val pdm: ParamDefMagnet { type Out = Directive1[String] } = new ParamDefMagnet {
type Out = Directive1[String]
def apply() = pdm2("name")
}
val directive: Directive1[String] = pdm()
// equivalent to:
val directive2: Directive1[String] = parameter("name")
All of this is what constitutes the simple parameter("name") call:
val p: Directive1[String] = parameter("name")
For how a Directive1[String] is applied in a DSL-ey way, see How do directives work in Spray?