I need to get a Numeric[T] if available (so I guess an Option[Numeric[T]]) for the following situation:
class Foo[T]() {
def t:T
def doSomeProcessing():Unit = ... // This is where I need an Option[Numeric[T]]
}
class Bar {
def foos: Seq[Foo[_]]
def doSomethingWithFoos():Unit = {
for (foo <- foos) {
foo.doSomeProcessing()
}
}
}
I can add ClassTag or TypeTag as necessary / helpful, but I'd like to avoid an explicit listing of each and every possible Numeric, which is what I have right now:
val numOpt: Option[Numeric[T]] = classTag[T] match {
case longTag if longTag == classTag[Long] => Some(Numeric.LongIsIntegral.asInstanceOf[Numeric[T]])
case intTag if intTag == classTag[Int] => Some(Numeric.IntIsIntegral.asInstanceOf[Numeric[T]])
...
case _ => None
}
Is there a more elegant / comprehensive solution? Thanks!
Edit: I tried doing:
class Foo[T](implicit num: Numeric[T] = null) {
def t:T
val numOpt:Option[Numeric[T]] = Option(num)
}
But that didn't work (numOpt = None for T = Long), probably because Foo is actually part of a long class hierarchy with multiple this / super calls...
Update: the issue is that Foo actually has four constructors, and all need to take an (implicit num: Numeric[T] = null), but only one of them is allowed to have a default parameter. I guess I would have to find a way to get rid of three of them, or manually feed in null as needed.
Try an implicit Numeric parameter with a default value:
class Foo[T] private(val t: T)(val numeric: Option[Numeric[T]])
object Foo {
def apply[T](t: T)(implicit numeric: Numeric[T] = null) = new Foo(t)(Option(numeric))
}
You can use it as such
class Bar {
//Note that I've explicitly put in Foo[Int] here because it doesn't understand it otherwise (not sure why).
def foos: Seq[Foo[_]] = Seq(Foo("blah"), Foo[Int](39))
def doSomethingWithFoos():Unit = {
for (foo <- foos) {
println(foo.t)
foo.numeric match {
case Some(num: Numeric[foo.t.type]) => println(num.plus(foo.t, foo.t))
case None => println("Not numeric")
}
}
}
}
Output:
blah
Not numeric
39
78
<script src="https://scastie.scala-lang.org/CDSbri6WQwSYtIoR4Swl8A.js"></script>
If you don't want the boilerplate of an apply method, you can also define your own method to supply Option instances and directly use an implicit in your constructor.
class Foo[T](val t: T)(implicit val numeric: Option[Numeric[T]])
implicit def implicitOption[T](implicit t: T = null): Option[T] = Option(t)
Link to Scastie: https://scastie.scala-lang.org/pUOw5tFNRtGZVbHNHx7QYw
Otherwise, you can use a nullable type instead of an Option.
class Foo[T](val t: T)(implicit val numeric: Numeric[T] = null)
Link to Scastie: https://scastie.scala-lang.org/AOGNZSirT0C7Cy0Po6vZXw
Related
I want to build a function that takes as input a generic function with one argument,
than parse the argument based on type and call the input function:
class PatternMatching {
val a = "test"
def test[T: TypeTag](callback: T => Unit): Unit = {
callback match {
case x if typeOf[T] <:< typeOf[String] => callback(a)
case x if typeOf[T] <:< typeOf[Array[Char]] => callback(a.toCharArray)
case _ => throw new IllegalArgumentException("error")
}
}
}
I see that type is correctly inferred but is not possible to invoke the function:
type mismatch;
found : PatternMatching.this.a.type (with underlying type String)
required: T
case x if typeOf[T] <:< typeOf[String] => callback(a)
I understand that it's expecting a type, but I can't find a way out.
You need explicit .asInstanceOf[T] with the method you've written:
callback(a.asInstanceOf[T])
Though, what you're trying to achieve is typically done with typeclass in Scala. I let the reader search about it but the general idea is you would have your method defined like this:
def test[T](callback: T => Unit)(implicit converter: ConverterFromString[T]): Unit = {
callback(converter.fromString(a))
}
And there would exist in scope some values of ConverterFromString for only some types you know how to handle.
The huge benefit of this approach is to be type-safe and if will raise errors at compile time rather than runtime if a type cannot be handled.
Using typeclass as suggested by #Gaël J works:
trait Converter[A] {
def conveterFromString(a: String): A
}
object Converter {
implicit val stringConverter: Converter[String] = new Converter[String] {
def conveterFromString(x: String): String = x
}
implicit val arrayConverter: Converter[Array[Char]] = new Converter[Array[Char]] {
def conveterFromString(x: String): Array[Char] = x.toCharArray
}
}
class PatternMatching {
val a = "test"
def test[A](callback: A => Unit)(implicit converter: Converter[A]): Unit =
callback(converter.conveterFromString(a))
}
Curious if anyone has a creative approach for the following:
def toDouble(any: Any): Option[Double] = // { if any has a .toDouble method call it else return None }
For instance, Int, String, Long all have a .toDouble method. I'd like it to be called if it exist (even non primitive types).
Ideally something like this (without .toString'ing everything first)
def toDouble(any: Any): Option[Double] = {
case any.hasToDouble => Try(any.toDouble).toOption
case _ => None
}
You can use
def doubleFromAny(in: Any): Option[Double] = {
Try{in.asInstanceOf[{def toDouble: Double}].toDouble}.toOption
}
The problem with this is any toDouble provided through an implicit won't work (so the string "4.5" would give you None). I also expect performance would not be great.
In the end, you need to figure out what types are possible and use something like Jon Anderson's answer to check and cast each type.
You can use pattern matching. This has the additional benefit of giving you more explicit control over how the conversion is done. (Eg, if you wanted to try additional string parsing)
def toDouble(any: Any): Option[Double] = {
any match {
case n:Int => Some(n.toDouble)
case n:Long => Some(n.toDouble)
case n:Double => Some(n.toDouble)
case s:String => Try(s.toDouble).toOption
case _ => None
}
}
def toDouble(a: Any): Option[Double] = try {
if (a == null) None else {
Some(a.toString.toDouble)
}
} catch {
case scala.util.control.NonFatal(e) => None
}
Others have suggested good answers. Another way I thought of doing was using implicit object. For your above example you could write something like:
sealed trait ImplicitType[T]
object ImplicitType{
implicit object IntType extends ImplicitType[Int]
implicit object StringType extends ImplicitType[String]
implicit object LongType extends ImplicitType[Long]
implicit object DoubleType extends ImplicitType[Double]
}
def toDouble[T : ImplicitType](n: T) : Option[Double] = {
Try(n.toString.toDouble).toOption
}
The above works because, the compiler constraint is from the availability of implicit objects in ImplicitType companion object. The context bound implicit def f: ImplicitType[T] by default searches for implicit objects inside companion object of ImplicitType. So now you can do things like:
val foo = toDouble(1) // Some(1.0)
val foo1 = toDouble("2") //Some(2.0)
val foo2 = toDouble(1L) //Some(1.0)
val foo3 = toDouble("s") //None
val foo4 = toDouble(1.23456e300d) //Some(1.23456E300)
In this way your toDouble function does not change at all. I couldn't think of a way to avoid toString sorry. Hope this works for you.
I need to check integrity of nested schemas and hence am writing case classes to do so. The main hurdle I am facing is the schema may have a field (say, name) either of a String or a Utf8 type and I want to accept both the instances. Is it possible to avoid having two case classes as
case class NameValueString(name: String, value: Double)
case class NameValueUtf8(name: Utf8, value: Double)
and something like
case class NameValue(name #(_:String | _:Utf8), value: Double)
The above expression certainly fails compilation.
Nikhil
One approach is so-called type classes:
trait StringLike[A] // sealed if you don't want anybody to implement it elsewhere
object StringLike {
implicit object StringEv extends StringLike[String] {}
implicit object Utf8Ev extends StringLike[Utf8] {}
}
case class NameValue[A](name: A, value: Double)(implicit val stringLike: StringLike[A])
Of course, StringLike will normally not be empty, but describe whatever common functionality you need from both String and Utf8.
You can match on the evidence:
def nameLength[A](nameValue: NameValue[A]) = nameValue.stringLike match {
case StringLike.StringEv =>
nameValue.name.length // calls String#length
case StringLike.Utf8Ev =>
nameValue.name.length // calls Utf8#length (assuming Utf8 has such method)
}
In this case the compiler will even know that A (and so the type of nameValue.name) is String in the first branch and Utf8 in the second.
Another pattern (doesn't require implicit arguments):
import scala.language.implicitConversions
class StringLike[A](name: A) {
override def toString = {
name match {
case s: String => s"String: $s"
case i: Int => s"Int: $i"
}
}
}
implicit def string2StringLike(s: String) = new StringLike(s)
implicit def int2StringLike(i: Int) = new StringLike(i)
case class NameValue[A](name: StringLike[A], value: String) {
override def toString = name.toString
}
NameValue("123", "123")
//> NameValue[String] = String: 123
NameValue(13, "123")
//> NameValue[Int] = Int: 13
NameValue(13.9, "123")
// error: type mismatch;
// found : Double(13.9)
// required: StringLike[?]
// NameValue(13.9, "123")
// ^
UPDATE
Here's how I see completed type class approach based on Alexey's answer:
trait StringLike[A] {
def toString(x: A): String
}
object StringLike {
implicit object StringStringLike extends StringLike[String] {
def toString(s: String) = s"String: $s"
}
implicit object IntStringLike extends StringLike[Int] {
def toString(i: Int) = s"Int: $i"
}
}
import StringLike._
case class NameValue[A](name: A, value: Double)(implicit ev: StringLike[A]) {
override def toString = ev.toString(name)
}
NameValue(1, 2.0)
//> NameValue[Int] = Int: 1
NameValue("123", 2.0)
//> NameValue[String] = String: 123
NameValue(2.0, 2.0)
// error: could not find implicit value for parameter ev:
// StringLike[Double]
// NameValue(2.0, 2.0)
// ^
UPDATE2
One more (using union type for type safety):
type ¬[A] = A => Nothing
type ¬¬[A] = ¬[¬[A]]
type ∨[T, U] = ¬[¬[T] with ¬[U]]
type |∨|[T, U] = { type λ[X] = ¬¬[X] <:< (T ∨ U) }
def nameLength[A: ClassTag: (Int |∨| String)#λ](nameValue: NameValue[A]) =
nameValue.name match {
case s:String => s.length
case i:Int => i + 1
}
As you are using case class already, if you just need different ways to create it, and you are ok on keeping your data represented in only one way, you can add your own apply method to enable the creation using different parameters.
case class NameValue(name: String, value: Double)
object NameValue{
def apply(name: Utf8, value: Double): NameValue = {
new NameValue( name.toString, value )
}
}
Alternatively, if you would like to pattern match and extract NameValue from different options, you may need to check Extractors, which is basically create your own unapply methods... check http://danielwestheide.com/blog/2012/11/21/the-neophytes-guide-to-scala-part-1-extractors.html
For example I have code looks like this:
class Parent
class Child1 extends Parent
class Child2 extends Parent
class Foo {
def retrieve(arg: String): List[Parent] = {
arg match {
case "Child1" => get[Child1]()
case "Child2" => get[Child2]()
}
}
def get[T: Manifest](): List[T] = ...
}
In the retrieve method, I want to simplify the code into one get method call only like this:
def retrieve(arg: String): List[Parent] = {
val t = arg match {
case "Child1" => ?
case "Child2" => ?
}
get[t]()
}
Is it possible to achieve this in scala?
UPDATE:
I tried the solution from the answer here but I got a problem, it doesn't work with overloaded get method, for example:
def get[T: Manifest](x: String): List[T] = ...
def get[T: Manifest, U: Manifest](x: String): List[(T, U)] = ...
For example, in the retrieve:
val t = arg match {
case "Child1" => manifest[Child1]
case "Child2" => manifest[Child2]
}
get("test")(t)
I got ambiguous reference to overloaded definition compile error on the line get("test")(t).
Manifest is basically deprecated. :
In Scala 2.10, scala.reflect.ClassManifests are deprecated, and it is
planned to deprecate scala.reflect.Manifest in favor of TypeTags and
ClassTags in an upcoming point release. Thus, it is advisable to
migrate any Manifest-based APIs to use Tags.
You should consider using the more modern ClassTag or TypeTag. In this case, ClassTag works better (since TypeTags can't be used in pattern matching):
def retrieve(arg: String): List[Parent] = {
val t = arg match {
case "Child1" => classTag[Child1]
case "Child2" => classTag[Child2]
}
get(t)
}
def get[T : ClassTag]: List[T] = list collect {
case x: T => x
}
You can read more about ClassTags, TypeTags, and their relationship to Manifest in the docs here.
In case it's not clear, this works because the type constraint on T is a context bound, meaning the method signature of get is equivalent to:
def get[T](implicit ev: ClassTag[T]): List[T]
So, when we call get(t), we're explicitly specifying the implicit parameter. Read more about context bounds here.
If the context bound or implicit parameter is confusing, you can also achieve your goals by making get non-generic:
def get(c: ClassTag[_]) = list collect {
case x if ClassTag(x.getClass) == c => x
}
This non-generic, non-implicit version might help you resolve your overloading issue.
Your question boils down to how to retrieve the Manifest of a given type. This can be done using the manifest method. Then you can explictly pass the manifest, to get.
class Foo {
def retrieve(arg: String): List[Parent] = {
val t = arg match {
case "Child1" => manifest[Child1]
case "Child2" => manifest[Child2]
}
get(t)
}
def get[T <: Parent: Manifest]: List[T] = ...
}
As a side note, you should probably use a map to retrieve the manifests (rather than pattern matching) so as to make it more easily editable, or possibly at one point replacing the hard-coded list of types with some init-time computation:
object Foo {
private val manifestByName = Map[String, Manifest[_<:Parent]](
"Child1" -> manifest[Child1],
"Child2" -> manifest[Child2]
)
}
class Foo {
def retrieve(arg: String): List[Parent] = {
val t = Foo.manifestByName.getOrElse(arg, sys.error(s"Invalid class name $arg"))
get(t)
}
def get[T <: Parent: Manifest]: List[T] = { println(manifest[T]); Nil }
}
Finally, note that Manifest is now deprecated, it was superseded with ClassTag\ TypeTag.
I am trying to write "better" (more idiomatic?) Scala code for the following circumstance:
I have a set of classes that will be identified by a reference field that belongs to a parallel set of reference case classes, something like the following:
abstract sealed class Ref(value: String)
case class ARef(value: String) extends Ref(value)
case class BRef(value: String) extends Ref(value)
case class CRef(value: String) extends Ref(value)
trait Referenced {
type refType <: Ref
val ref: refType
}
trait A extends Referenced { type refType = ARef }
trait B extends Referenced { type refType = BRef }
trait C extends Referenced { type refType = CRef }
Another class (which will probably turn into the state type of a State monad) will contain lists of these types, and provide a function to retrieve an object, given its reference. I want this returned value to be appropriately typed, i.e. given
val aRef = ARef("my A ref")
I want to be able to make a call like:
val myA: Option[A] = context.get[A](aRef)
and be sure to get back an Option[A], not just an Option[Referenced]. My best attempt to achieve this so far looks something like the following:
trait Context {
// ... other stuff ...
protected val aList: List[A]
protected val bList: List[B]
protected val cList: List[C]
def get[R <: Referenced](ref: R#refType): Option[R] = {
val result = ref match {
case aRef: ARef => aList.find(_.ref == aRef)
case bRef: BRef => bList.find(_.ref == bRef)
case cRef: CRef => cList.find(_.ref == cRef)
case _ => throw new RuntimeException("Unknown Ref type for retrieval: "+ref)
}
result.asInstanceOf[Option[R]]
}
}
which seems to work correctly, but has that smelly "asInstanceOf" call in it. I would be interested in seeing ideas on how this might be done better (and check that I haven't just missed an obvious simpler solution).
Note that for other reasons, I have thus far elected to go with abstract typing rather than parameter types (trait A extends Referenced[ARef] style), but could change this if the reasons were compelling enough.
The machinery needed to do this without casting really isn't all that heavy in this case ... it's just another example of a functional dependency.
In what follows we rely on the fact that type Ref is sealed so that we can simply enumerate the alternatives. Your Ref and Reference hierarchies remain unchanged, and we add a relation type Rel to both express the type-level correspondence between the two, and to make an appropriate value-level selection,
trait Rel[Ref, T] {
def lookup(as: List[A], bs: List[B], cs: List[C])(ref: Ref) : Option[T]
}
object Rel {
implicit val relA = new Rel[ARef, A] {
def lookup(as: List[A], bs: List[B], cs: List[C])(ref: ARef) : Option[A] =
as.find(_.ref == ref)
}
implicit val relB = new Rel[BRef, B] {
def lookup(as: List[A], bs: List[B], cs: List[C])(ref: BRef) : Option[B] =
bs.find(_.ref == ref)
}
implicit val relC = new Rel[CRef, C] {
def lookup(as: List[A], bs: List[B], cs: List[C])(ref: CRef) : Option[C] =
cs.find(_.ref == ref)
}
}
Now we can reimplement Context without pattern matches or casts as follows,
trait Context {
// ... other stuff ...
protected val aList: List[A] = ???
protected val bList: List[B] = ???
protected val cList: List[C] = ???
def get[R <: Ref, T](ref: R)(implicit rel: Rel[R, T]): Option[T] =
rel.lookup(aList, bList, cList)(ref)
}
And we can use this new definition like so,
object Test {
def typed[T](t: => T) {} // For pedagogic purposes only
val context = new Context {}
val aRef = ARef("my A ref")
val myA = context.get(aRef)
typed[Option[A]](myA) // Optional: verify inferred type of myA
val bRef = BRef("my B ref")
val myB = context.get(bRef)
typed[Option[B]](myB) // Optional: verify inferred type of myB
val cRef = CRef("my C ref")
val myC = context.get(cRef)
typed[Option[C]](myC) // Optional: verify inferred type of myC
}
Notice that the resolution of the implicit Rel argument to get computes the type of the corresponding Reference from the type of the ref argument, so we're able to avoid having to use any explicit type arguments at get's call-sites.
I am just going to reiterate my own (current) "answer" for my question, because I thought it would be interesting/instructive to allow readers to vote it up or down to generate a more direct comparison with answers provided by others.
trait Context {
// ... other stuff ...
protected val aList: List[A]
protected val bList: List[B]
protected val cList: List[C]
def get[R <: Referenced](ref: R#refType): Option[R] = {
val result = ref match {
case aRef: ARef => aList.find(_.ref == aRef)
case bRef: BRef => bList.find(_.ref == bRef)
case cRef: CRef => cList.find(_.ref == cRef)
case _ => throw new RuntimeException("Unknown Ref type for retrieval: "+ref)
}
result.asInstanceOf[Option[R]]
}
}