Shapeless lenses usage with a string definition - scala

I would like use shapeless lenses to access value of the case class field by a String definition.
I know this code works.
case class Test(id: String, calc: Long)
val instance = Test("123232", 3434L)
val lens = lens[Test] >> 'id
val valueOfFieldId = lens.get(instance)
But what I am trying to do is:
val fieldName = "id"
val lens = lens[Test] >> fieldName.witness
//I typed .witness because it was expecting a witness (if I am not wrong)
val valueOfFieldId = lens.get(instance)
But with this code, I am getting this error.
Could not find implicit value for parameter mkLens: shapeless.MkFieldLens[A$A148.this.Test,A$A148.this.str.type]
def get$$instance$$lll = lll;/* ###worksheet### generated $$end$$ */ lazy val lens = lens[Test] >> str.witness
Is it possible to get the value of case class field with a String definition?
Thanks.

You are supposed to use Symbol ('id) here rather than String ("id").
Creating Symbol from String
Symbol(fieldName)
is runtime operation and Shapeless operates in compile time.
Why can't you use symbols?

Related

Scala: Case class with generic function argument

I have the following case class.
case class CustomAttributeInfo[T,Y](
attribute:MyAttribute[_],
fieldName:String,
valueParser:T => Y){}
The case class takes three values.
The last argument is a function that will parse an input of any type and return the part of the input we wish to keep.
(Imagine, for just one example, I pass in a jsonstring, convert to json object, and extract an Int).
The companion object will supply a range of functions that we can pass to the case class. The one shown here, simply takes the input as a string and returns it as a string (the most simple possible example).
object CustomAttributeInfo {
val simpleString = (s:String) => s
}
I create the case class as follows:
CustomAttributeInfo(MyAttribute(var1, var2), name, CustomAttributeInfo.simpleString)
Later, I call the function 'valueParser'
customAttributeInfo.valueParser(k)
Compilation error
Error:(366, 69) type mismatch;
found : k.type (with underlying type String)
required: _$13
case Some(info) => Some((info.attribute, info.valueParser(k)))
I am not a generics expert (obviously). I have done some reading, but I have not seen a discussion about a case like this. Any advice and explanation would be most welcome
You haven't provide enough information to answer your question.
The following code compiles.
If you still have compile error provide MCVE.
case class MyAttribute[_](var1: Any, var2: Any)
case class CustomAttributeInfo[T,Y](attribute:MyAttribute[_], fieldName:String, valueParser:T => Y) {}
object CustomAttributeInfo {
val simpleString = (s:String) => s
}
val var1: Any = ???
val var2: Any = ???
val name: String = ???
val customAttributeInfo = CustomAttributeInfo(MyAttribute(var1, var2), name, CustomAttributeInfo.simpleString)
val k = "abc"
customAttributeInfo.valueParser(k)
#Dmytro was right that a simple example compiled. In my actual codebase code, however, we needed to be specific about the type.
This worked:
object CustomAttributeInfo {
type T = Any
val simpleString = (s:T) => s.toString
}

Is it possible to specify that a type will have a certain parameters in its constructor? Scala

So I have a class that suppose to use generic type, but that type should be with certain characteristics
It needs to have defined method calculate
It needs to have constructor that accepts Seq[Double]
At the moment I have a trait
trait HasCalculate {def calculate(): Double}
And I use it this way:
val pars = Seq(1.0, 2.0)
val calc = new Calc1(pars) with HasCalculate
val res = calc.calculate
When I want to use another calculator I put Calc2 instead Calc1 in the code of the class. But I would like to do it generic way, something like:
class MyClass[T]{
val pars = Seq(1.0, 2.0)
val calc = new T(pars) with HasCalculate
val res = calc.calculate
}
But how to define that T has constructor that accepts Seq[Double]?
What you're describing doesn't sound like it's possible in Scala (which doesn't really have facilities for abstracting over constructors), and without knowing your larger goals more specifically it's hard to offer good advice, but the following is a Scala-idiomatic solution that provides the kind of usage it looks like you want for MyClass and that is specifically designed to let you use generic types while constraining those types to have certain operations.
The first step is to write a type class that captures the operations you need:
trait Calculable[A] {
def create(values: Seq[Double]): A
def calculate(a: A): Double
}
You can think of instances of this type as "evidence" that you can perform these operations on some A.
Next you'd write your MyClass like this:
class MyClass[T: Calculable] {
private val instance = implicitly[Calculable[T]]
val pars = Seq(1.0, 2.0)
val calc: T = instance.create(pars)
val res: Double = instance.calculate(calc)
}
The T: Calculable part is a "context bound", which specifies that there must be implicit evidence that T has a Calculable instance. It's a constraint that says "T can be any type, as long as we know how to do the Calculable operations on it".
Now you could write a particular class that could be used as T like this:
class MyCalculation(vs: Seq[Double]) {
def calculate(): Double = vs.sum
}
object MyCalculation {
implicit val calculableInstance: Calculable[MyCalculation] =
new Calculable[MyCalculation] {
def create(values: Seq[Double]): MyCalculation = new MyCalculation(values)
def calculate(a: MyCalculation): Double = a.calculate()
}
}
And you get the usage you want:
scala> val myClass = new MyClass[MyCalculation]
myClass: MyClass[MyCalculation] = MyClass#646bf8a6
scala> myClass.res
res0: Double = 3.0
If you control the definition of MyCalculation, the most convenient place to define its implicit Calculable[MyCalculation] is the MyCalculation companion object, but one of the advantages of the type class approach is that it separates the definition of operations on a type from the definition of the type, and these instances can be defined separately.
I came up with an answer myself I would like to share...
So instead MyClass has type parameter it could have a function as parameter, something like this:
class MyClass(f:(Seq[Double])=>HasCalculate){
val pars = Seq(1.0, 2.0)
val calc = f(pars)
val res = calc.calculate
}
And then to provide an anonymous function with the constructor in its body:
val myClass = new MyClass((s:Seq[Double])=>new Calc1(s) with HasCalculate)
Of course this looks ugly but in my case it appears to be more practical than Travis's solution, since I have lots of calculators and I don't intend to create that factory object for each of them or each time I want to run a calculator through MyClass. I just copy this line of code and replace Calc1 with Calc99...
So if you have few calculators and lots of calls to MyClass, definitely Trevis's solution is better, otherwise this might be useful...

In Scala reflection, why reflection function on TypeTag still has type erasure?

Considering the following scala program:
val arr: Seq[String] = Seq("abc", "def")
val cls = arr.head.getClass
println(cls)
val ttg: TypeTag[Seq[String]] = typeOf[Seq[String]]
val fns = ttg.tpe
.members
val fn = fns
.filter(_.name.toString == "head")
.head // Unsafely access it for now, use Option and map under normal conditions
.asMethod // Coerce to a method symbol
val fnTp = fn.returnType
println(fnTp)
val fnCls = ttg.mirror.runtimeClass(fnTp)
assert(fnTp == cls)
Since TypeTag has both Seq and String information, I would expect that fn.returnType give the correct result "String", but in this case I got the following program output:
cls = class java.lang.String
fnTp = A
And subsequently throw this exception:
A needed class was not found. This could be due to an error in your runpath. Missing class: no Java class corresponding to A found
java.lang.NoClassDefFoundError: no Java class corresponding to A found
at scala.reflect.runtime.JavaMirrors$JavaMirror.typeToJavaClass(JavaMirrors.scala:1258)
at scala.reflect.runtime.JavaMirrors$JavaMirror.runtimeClass(JavaMirrors.scala:202)
at scala.reflect.runtime.JavaMirrors$JavaMirror.runtimeClass(JavaMirrors.scala:65)
Obviously type String was erased, leaving only a wildcard type 'A'
Why TypeTag is unable to yield the correct erased type as intended?
Seq.head is defined as def head: A. And fn is just a method symbol of the method head from a generic class Seq[A], it doesn't know anything about the concrete type. So its returnType is exactly that A just as defined in Seq.
If you want to know what that A would be in some concrete Type, you'd have to specify that explicitly. For instance, you can use infoIn on the method symbol:
scala> val fnTp = fn.infoIn(ttg.tpe)
fnTp: reflect.runtime.universe.Type = => String
scala> val fnRetTp = fnTp.resultType
fnRetTp: reflect.runtime.universe.Type = String

Scala val and type at the same time

While reading Scala source code i came across the following in scala/package.scala
I don't quite get why we need trait and val at the same time. The trait keyword will alias the class, then why do we need the val ?
type StringBuilder = scala.collection.mutable.StringBuilder
val StringBuilder = scala.collection.mutable.StringBuilder
// Numeric types which were moved into scala.math.*
type BigDecimal = scala.math.BigDecimal
val BigDecimal = scala.math.BigDecimal
type BigInt = scala.math.BigInt
val BigInt = scala.math.BigInt
type Equiv[T] = scala.math.Equiv[T]
val Equiv = scala.math.Equiv
Am including a Generic Type example as well to get more understanding about the multiple declarations there was well.
It's because type only defines a type alias; it doesn't alias the type's companion object.
The companion object usually contains handy methods, especially an apply method for creating objects of the type. If you don't do the val, you won't have access to those methods, at least not under the name of the alias.

Scala Getting class type from string representation

I have a class name string representation
val cls = Class.forName("clsName")
def fromJson[T: Manifest](me: String): T = {
Extraction.extract[T](net.liftweb.json.parse(me))
}
I would like to use it as T:manifest i.e
JsonConverter.fromJson[cls.type](stringData)
this returns an error
tried also
val t = Manifest.classType(cls)
JsonConverter.fromJson[t](stringData) // compile error
what is the best way to it ? is there a way to avoid using reflection ?
You could try something like this:
val cls = Class.forName(myClassName)
val m = Manifest.classType(cls)
val myObj:Any = JsonConverter.fromJson(stringData)(m)
One nuance to this approach is that you have to explicitly type the object as an Any. This is because you don't have the class as compile time and the call to classType is not supplied its type param so the Manifest returned is Manifest[Nothing]. Not ideal, but it works.