How to write a bounded Generic Class in scala - scala

I need to write a generic class that can only allow the types Long,Double in place of [V]
class DummyGenericClass[V](data:Seq[V])
Also, there will be an implementation difference based on the type. I want to do something like
val typ = if (V is Long) "x" else "y"
What is the recommended/best practice in scala to write such code?

You can achieve it using sealed trait, which limits possible implementations to those that are defined in the same file:
sealed trait DummyGenericClass[V] {
val data: Seq[V]
val typ: String
}
class LongClass(val data: Seq[Long]) extends DummyGenericClass[Long] {
val typ = "x"
}
class DoubleClass(val data: Seq[Double]) extends DummyGenericClass[Double] {
val typ = "y"
}
If you want to have a generic constructor for DummyGenericClass the type safe way to do it is to use typeclass combined with factory pattern:
object DummyGenericClass {
trait Factory[T] {
def create(seq: Seq[T]): DummyGenericClass[T]
}
object Implicits {
implicit val longProvider =
new Factory[Long] {
def create(seq: Seq[Long]) = new LongClass(seq)
}
implicit val doubleProvider =
new Factory[Double] {
def create(seq: Seq[Double]) = new DoubleClass(seq)
}
}
def apply[T: Factory](seq: Seq[T]) = implicitly[Factory[T]].create(seq)
}
Which you can use the following way:
import DummyGenericClass.Implicits._
val foo = DummyGenericClass(Seq.empty[Long])
val bar = DummyGenericClass(Seq.empty[Double])
// Won't compile:
val baz = DummyGenericClass(Seq.empty[String])
The other way, that doesn't require defining a typeclass to create DummyGenericClass instances, is to pass ClassTag bound to T in the factory method. However this solution is not recommended since it's not a type safe way, as it allows one to pass type argument that is not supported and will fail at runtime.
If you want to have a generic method that uses this constructor, you have to add DummyGenericClass.Factory context bound to that method too:
def add[T: DummyGenericClass.Factory]
(a: DummyGenericClass[T], b: DummyGenericClass[T]) =
DummyGenericClass(a.data ++ b.data)
import DummyGenericClass.Implicits._
add(DummyGenericClass(Seq(1.0)), DummyGenericClass(Seq(2.0)))

Related

Group TypeClass instances by type parameter

Suppose, I have 2 typeclasses:
trait Foo[A] {
...
}
trait Bar[A] {
...
}
and then I collect their instances into collections:
val seqFoo : Set[Foo[_]] = ...
val seqBar : Set[Bar[_]] = ...
is there a way to combine this seqs into something like this:
val fooBar = (Foo[Int],Bar[Int]), ... , (Foo[String],Bar[String])
Maybe pattern matching function or type tags is an answer, but I believe this case should have more straightforward solution
For example you can make your type classes abstract classes rather than traits (then they can have parameters), add implicit TypeTag parameters, and make groupBy for your collections.
import scala.reflect.runtime.universe.{TypeTag, Type}
// type class
abstract class Foo[A](implicit val ttag: TypeTag[A]) {
def foo(): String // dummy method just to distinguish instances upon checking
}
// instances
object Foo1 {
implicit val intFoo: Foo[Int] = new Foo[Int]() {
override def foo(): String = "Foo1.intFoo"
}
implicit val strFoo: Foo[String] = new Foo[String]() {
override def foo(): String = "Foo1.strFoo"
}
}
object Foo2 {
implicit val intFoo: Foo[Int] = new Foo[Int]() {
override def foo(): String = "Foo2.intFoo"
}
implicit val boolFoo: Foo[Boolean] = new Foo[Boolean]() {
override def foo(): String = "Foo2.boolFoo"
}
}
object Foo3 {
implicit val intFoo: Foo[Int] = new Foo[Int]() {
override def foo(): String = "Foo3.intFoo"
}
implicit val strFoo: Foo[String] = new Foo[String]() {
override def foo(): String = "Foo3.strFoo"
}
implicit val boolFoo: Foo[Boolean] = new Foo[Boolean]() {
override def foo(): String = "Foo3.boolFoo"
}
}
val seqFoo : Set[Foo[_]] = Set(Foo1.intFoo, Foo1.strFoo, Foo2.intFoo, Foo2.boolFoo, Foo3.intFoo, Foo3.strFoo, Foo3.boolFoo)
val grouped: Map[Type, Set[Foo[_]]] = seqFoo.groupBy(_.ttag.tpe)
// checking that instances are grouped by type
grouped.view.mapValues(_.map(_.foo())).foreach(println)
//(Int,HashSet(Foo3.intFoo, Foo1.intFoo, Foo2.intFoo))
//(String,HashSet(Foo1.strFoo, Foo3.strFoo))
//(Boolean,HashSet(Foo2.boolFoo, Foo3.boolFoo))
Simlarly you can do groupBy for Bar and then do whatever you want with Map[Type, Set[Foo[_]]] and Map[Type, Set[Bar[_]]]. For example merge the Maps
val grouped: Map[Type, Set[Foo[_]]] = ???
val grouped1: Map[Type, Set[Bar[_]]] = ???
val merged: Map[Type, (Set[Foo[_]], Set[Bar[_]])] =
(grouped.keySet union grouped1.keySet)
.map(tpe => tpe -> (grouped(tpe), grouped1(tpe)))
.toMap
I'll copy from my comment. Instances of type classes are intended to be resolved automatically (via implicit resolution) by compiler at compile time. Collecting the instances manually seems weird, so does collecting them at runtime.
My typeclasses instances implement decoder/encoder logic. Also they contain some meta information (name particularly). So i would like to check name-to-type accordance and generate unique names, based on how many instances have same name but different type parameter.
Although names of implicits can sometimes make impact on implicit resolution (1 2 3 4), normally you shouldn't be interested much in names of implicits, nor in name-to-type correspondence. Maybe you should provide some code snippet so that we can understand your setting and goals. Maybe what you need can be done at compile time and/or automatically.
Alternatively, if you prefer to keep type classes traits or you can't modify their code, you can use magnet pattern (1 2 3 4 5 6 7 8)
trait Foo[A] {
def foo(): String
}
implicit class Magnet[F[_], A: TypeTag](val inst: F[A]) {
def tpe: Type = typeOf[A]
}
val seqFoo = Set[Magnet[Foo, _]](Foo1.intFoo, Foo1.strFoo, Foo2.intFoo, Foo2.boolFoo, Foo3.intFoo, Foo3.strFoo, Foo3.boolFoo)
val grouped: Map[Type, Set[Magnet[Foo, _]]] = seqFoo.groupBy(_.tpe)
// checking that instances are grouped by type
grouped.view.mapValues(_.map(_.inst.foo())).foreach(println)
//(String,HashSet(Foo1.strFoo, Foo3.strFoo))
//(Int,HashSet(Foo3.intFoo, Foo1.intFoo, Foo2.intFoo))
//(Boolean,HashSet(Foo2.boolFoo, Foo3.boolFoo))
Using the "Prolog in Scala" to find available type class instances

Is there some way in scala that I can return a type?

I have a lot of classes such as DataFrameFlow, TextFlow, RDDFlow. They all derive from base class Flow.
Now I want to write a function judgeFlow which can read from a path: String and return something representing exact Flow type from which I can create corresponding instance. The whole code seems like the following
def judgeFlow(path:String) = /*1*/ {
Flow.getStoreType(path) match {
case StoreType.tdw =>
DataFrameFlow
case StoreType.hdfs =>
TextFlow
}
}
def createFlow(typeInfo:/*2*/) = /*3*/{
new typeInfo()
}
However, I don't know how to write in place 1, 2 and 3.
EDIT
Knowing how to construct them is not enough here, because I also want the following:
pattern matching through typeInfo
some ways to do asInstanceOf
EDIT 2
Definition of Flow
abstract class Flow(var outputName: String) extends Serializable{
def this() = this("")
...
}
Definition of DataFrameFlow
class DataFrameFlow(d: DataFrame, path: String) extends Flow {
var data: DataFrame = d
def this(data: DataFrame) = this(data, "")
def this(path: String) = this(null, path)
def this() = this(null, "")
...
}
Pattern matching can't return different types from different cases. The type returned by pattern matching is the least upper bound of types returned in cases.
When someone wants to return different types, most probably he/she wants a type class.
sealed abstract class Flow
class DataFrameFlow extends Flow
class TextFlow extends Flow
class RDDFlow extends Flow
trait JudgeFlow[In] {
type Out <: Flow
def judgeFlow(in: In): Out
}
object JudgeFlow {
implicit val `case1`: JudgeFlow[???] { type Out = DataFrameFlow } = ???
implicit val `case2`: JudgeFlow[???] { type Out = TextFlow } = ???
implicit val `case3`: JudgeFlow[???] { type Out = RDDFlow } = ???
}
def judgeFlow[In](in: In)(implicit jf: JudgeFlow[In]): jf.Out = jf.judgeFlow(in)
But the trouble is that types are resolved at compile time. You seem to want to choose a case based on a value of string i.e. at runtime. So you can't return more specific types than just Flow at compile time.
flatMap with Shapeless yield FlatMapper not found
It's hard to guess your use case completely.
But using Scala reflection you can try
import scala.reflect.runtime.universe._
import scala.reflect.runtime.currentMirror
def judgeFlow(path:String): Type = {
Flow.getStoreType(path) match {
case StoreType.tdw =>
typeOf[DataFrameFlow]
case StoreType.hdfs =>
typeOf[TextFlow]
}
}
def createFlow(typeInfo: Type): Flow = {
val constructorSymbol = typeInfo.decl(termNames.CONSTRUCTOR).asMethod
val classSymbol = typeInfo.typeSymbol.asClass
val classMirror = currentMirror.reflectClass(classSymbol)
val constructorMirror = classMirror.reflectConstructor(constructorSymbol)
constructorMirror().asInstanceOf[Flow]
}

Scala: specifying a generic type that is constructible from another

I would like to do something which, more or less, boils down to the following:
def foo[S](x: String): S = S(x) // S(x) does not compile
So that if I have:
case class S1(x:String)
case class S2(x:String)
...
case class Sn(x:String)
I can write foo[Sx]("bar") to get Sx("foo").
Is there any way to specify that an instance of a class should be constructible from an instance of another (in this example String) and to actually invoke the constructor in a generic way?
You may use reflection (see #Ben Reich answer for detailed answer)
def foo[S:ClassTag](x: String): S = {
val runtimeClass = implicitly[ClassTag[S]].runtimeClass
val constructor = runtimeClass.<get a constructor with single String argument>
constructor(x) .asInstanceOf[S]
}
Or a type class that can construct an instance:
trait CanConstruct[S] {
def apply(x:String):S
}
def foo[S:CanConstruct](x: String): S = {
val constructor = implicitly[CanConstruct[S]]
constructor(x).asInstanceOf[S]
}
UPD You would need an instance of the type class for every type you wish to construct:
implicit val s1constructor = new CanConstruct[S1] { def apply(x:String) = S1(x) }
...
Also it seems to be the case for conversion functions:
implicit val convertStringToS1 = S1(_)
implicit val convertStringToS2 = S2(_)
...
Using reflection:
import reflect.ClassTag
def foo[S: ClassTag](x: String) = implicitly[ClassTag[S]]
.runtimeClass
.getConstructors
.map(a => a -> a.getParameters)
.collectFirst {
case (constructor, Array(p)) if p.getType == classOf[String]
=> constructor.newInstance(x).asInstanceOf[S]
}
Which will return an Option[S], if the proper constructor is found.
I sort of solved it with a macro:
object Construct {
import scala.language.experimental.macros
import scala.reflect.macros.Context
def construct[A,B](x:B):A = macro constructImpl[A,B]
def constructImpl[A: c.WeakTypeTag,B](c:Context)(x:c.Expr[B]) = {
import c.universe._
c.Expr[A](q"""new ${c.weakTypeOf[A]}(${x.tree})""")
}
}
I now can write things like:
case class Foo(x:String)
case class Bar(x:Int)
construct[Foo,String]("foo")
construct[Bar,Int](42)
It would be nice to find a way to avoid having to write the second type parameter, though.

Could not find implicit value for parameter x

Just when I thought I understood the basics of Scala's type system... :/
I'm trying to implement a class that reads the contents of a file and outputs a set of records. A record might be a single line, but it could also be a block of bytes, or anything. So what I'm after is a structure that allows the type of Reader to imply the type of the Record, which in turn will imply the correct Parser to use.
This structure works as long as MainApp.records(f) only returns one type of Reader. As soon as it can return more, I get this error:
could not find implicit value for parameter parser
I think the problem lies with the typed trait definitions at the top, but I cannot figure out how to fix the issue...
// Core traits
trait Record[T]
trait Reader[T] extends Iterable[Record[T]]
trait Parser[T] {
def parse(r: Record[T]): Option[Int]
}
// Concrete implementations
class LineRecord[T] extends Record[T]
class FileReader[T](f:File) extends Reader[T] {
val lines = Source.fromFile(f).getLines()
def iterator: Iterator[LineRecord[T]] =
new Iterator[LineRecord[T]] {
def next() = new LineRecord[T]
def hasNext = lines.hasNext
}
}
trait TypeA
object TypeA {
implicit object TypeAParser extends Parser[TypeA] {
def parse(r: Record[TypeA]): Option[Int] = ???
}
}
trait TypeB
object TypeB {
implicit object TypeBParser extends Parser[TypeB] {
def parse(r: Record[TypeB]): Option[Int] = ???
}
}
// The "app"
object MainApp {
def process(f: File) =
records(f) foreach { r => parse(r) }
def records(f: File) = {
if(true)
new FileReader[TypeA](f)
else
new FileReader[TypeB](f)
}
def parse[T](r: Record[T])(implicit parser: Parser[T]): Option[Int] =
parser.parse(r)
}
First off you must import the implicit object in order to use them:
import TypeA._
import TypeB._
That's not enough though. It seems like you're trying to apply implicits dynamically. That's not possible; they have to be found compile time.
If you import the objects as above and change the records so that the compiler finds the correct generic it will run fine:
def records(f: File) = new FileReader[TypeA](f)
But then it may not be what you were looking for ;)
The problem is that the return type of your records method is basically FileReader[_] (since it can return either FileReader[TypeA] or FileReader[TypeB]), and you don't provide an implicit argument of type Parser[Any]. If you remove the if-expression the return type is inferred to FileReader[TypeA], which works fine. I'm not sure what you're trying to do, but obviously the compiler can't select implicit argument based upon a type that is only known at runtime.
1) Using type with implicit inside as type parameter - doesn't bind this implicit to the host type, to do this change objects to the traits and mix them instead of generalizing (type-parametrizing):
def records(f: File) = {
if(true)
new FileReader(f) with TypeA
else
new FileReader(f) with TypeB
}
2) The parser should be in scope of function that calls parse. So you may try smthg like that:
def process(f: File) = {
val reader = records(f);
import reader._
reader foreach { r => parse(r) }
}
PlanB) Simpler alternative is to define type-parameter specific implicit methods inside the AppMain (or some trait mixed in), but it will work only if TypeA/TypeB is known on compile time, so records method can return concrete type:
implicit class TypeAParser(r: Record[TypeA]) {
def parse: Option[Int] = ???
}
implicit class TypeBParser(r: Record[TypeB]) {
def parse: Option[Int] = ???
}
def process[T <: TypeAorB](f: File) =
records[T](f).foreach(_.parse)
def recordsA[T <: TypeAorB](f: File) = new FileReader[T](f)
Here is, I think, the full set of modifications you need to do to get where I think you want to go.
import scala.io.Source
import java.io.File
import reflect.runtime.universe._
// Core traits
trait Record[+T]
trait Reader[+T] extends Iterable[Record[T]]
trait Parser[-T] {
def parse(r: Record[T]): Option[Int]
}
// Concrete implementations [unmodified]
class LineRecord[T] extends Record[T]
class FileReader[T](f:File) extends Reader[T] {
val lines = Source.fromFile(f).getLines()
def iterator: Iterator[LineRecord[T]] =
new Iterator[LineRecord[T]] {
def next() = new LineRecord[T]
def hasNext = lines.hasNext
}
}
sealed trait Alternatives
case class TypeA() extends Alternatives
object TypeA {
implicit object TypeAParser extends Parser[TypeA] {
def parse(r: Record[TypeA]): Option[Int] = ???
}
}
case class TypeB() extends Alternatives
object TypeB {
implicit object TypeBParser extends Parser[TypeB] {
def parse(r: Record[TypeB]): Option[Int] = ???
}
}
class ParseAlternator(parserA: Parser[TypeA], parserB: Parser[TypeB]) extends Parser[Alternatives] {
def parse(r: Record[Alternatives]): Option[Int] = r match {
case x: Record[TypeA #unchecked] if typeOf[Alternatives] =:= typeOf[TypeA] => parserA.parse(x)
case x: Record[TypeB #unchecked] if typeOf[Alternatives] =:= typeOf[TypeB] => parserB.parse(x)
}
}
object ParseAlternator {
implicit def parseAlternator(implicit parserA: Parser[TypeA], parserB: Parser[TypeB]): Parser[Alternatives] = new ParseAlternator(parserA, parserB)
}
// The "app"
object MainApp {
import ParseAlternator._
def process(f: File) =
records(f) foreach { r => parse(r) }
def records(f: File): Reader[Alternatives] = {
if(true)
new FileReader[TypeA](f)
else
new FileReader[TypeB](f)
}
def parse[T](r: Record[T])(implicit parser: Parser[T]): Option[Int] =
parser.parse(r)
}
The gist of it is: all of this would be completely classsical if only your parse instance did not have to pattern-match on a generic type but dealt directly with an Alternative instead.
It's this limitation (inherited from the JVM) that scala can't properly pattern-match on an object of a parametric type that requires the reflection & typeOf usage. Without it, you would just have type alternatives for your content (TypeA, TypeB), which you would add to a sealed trait, and which you would dispatch on, in an implicit that produces a Parser for their supertype.
Of course this isn't the only solution, it's just what I think is the meeting point of what's closest to what you're trying to do, with what's most idiomatic.

Call a "static" method belonging to a generic type in scala

Is there a way in scala to call a method belonging to a type? For example, suppose I have a trait called Constructable that describes types than can construct a default instance of themselves. Then, I can write the following code:
trait Constructable[A] {
def construct: A
}
class Foo(x: Int) extends Constructable[Foo] {
def construct = new Foo(0)
}
def main(args: Array[String]) {
val f = new Foo(4)
println(f.construct)
}
This is ok, but what I really want is to be able to construct a default object given only the type of object. For example, suppose I want to accept a list of constructables and prepend a default object at the beginning of the list:
def prependDefault1[A <: Constructable[A]](c: List[A]): List[A] = {
val h = c.head
h.construct :: c
}
The above code works, but only if c is not empty. What I'd really like is to write something like the following:
def prependDefault2[A <: Constructable[A]](c: List[A]): List[A] = {
A.construct :: c
}
Is there any way to achieve this, possibly by changing the definition of a Constructable so that the construct method belongs to the "class" rather than the "instance" (to use Java terminology)?
You can't do this way, but you can do this using typeclasses:
trait Constructable[A] {
def construct: A
}
// 'case' just so it's printed nicely
case class Foo(x: Int)
// implicit vals have to be inside some object; omitting it here for clarity
implicit val fooConstructable = new Constructable[Foo] {
def construct = new Foo (0)
}
def prependDefault2[A : Constructable](c: List[A]): List[A] = {
implicitly[Constructable[A]].construct :: c
}
And then:
scala> prependDefault2(Nil: List[Foo])
res7: List[Foo] = List(Foo(0))
Some final remarks:
Implicits have to live inside an object. There are three places it can be located:
object Constructable { implicit val fooConstructable = ... (companion object of the typeclass trait)
object Foo { implicit val fooConstructable = ... (companion object of the class we implement typeclass for)
object SomethingElse { implicit val fooConstructable = ... (some random unrelated object)
Only in the last case you need to use import SomethingElse._ in order to be able to use the implicit.