I am trying to modify this standard example to print values with the types.
And I am stuck with p.MirroredElemTypes. I haven't found any API to traverse and stringify types.
To check MirroredElemTypes you can just summon
import scala.deriving.Mirror
case class A(i: Int, s: String, b: Boolean)
val m = summon[Mirror.Of[A]]
summon[m.MirroredElemTypes =:= (Int, String, Boolean)] // compiles
But if you want to print MirroredElemTypes you can do the following.
For some reason Typeable doesn't work now but in its error message it prints the type
// scalaVersion := "3.0.2"
// libraryDependencies += "org.typelevel" %% "shapeless3-typeable" % "3.0.3"
import shapeless3.typeable.Typeable
summon[Typeable[m.MirroredElemTypes]].describe
// Typeable for sum type scala.*:[scala.Int, scala.*:[scala.Predef.String, scala.*:[scala.Boolean, scala.Tuple$package.EmptyTuple]]] with no Mirror
Alternatively you can write a simple macro
import scala.quoted.*
inline def describe[A]: String = ${describeImpl[A]}
def describeImpl[T: Type](using Quotes): Expr[String] = {
import quotes.reflect.*
Literal(StringConstant(TypeRepr.of[T].dealias.show)).asExprOf[String]
}
// in a different file
describe[m.MirroredElemTypes]
// scala.*:[scala.Int, scala.*:[scala.Predef.String, scala.*:[scala.Boolean, scala.Tuple$package.EmptyTuple]]]
In Scala 3.2.0 + Shapeless 3.2.0 Typeable works properly
https://scastie.scala-lang.org/DmytroMitin/1R6N3ZOJS46DJJqtQDU0lw
Related
Constructing an object based on passed parameter. But the parameter is not String.
I found the solution how to do it with String
Scala instantiate objects from String classname
but I believe that it can be done nicer.
Let's say the following classes:
sealed trait Figure
object Figure {
final case class Circle(radius: Double) extends Figure
final case class Square(a: Double) extends Figure
}
And let's define a function (which doesn't make sense) which take a parameter based on I can invoke the proper constructor:
val construct123: Figure => Either[String, Figure] = (figure: Figure) => Right(figure.apply(1.23))
I want to invoke
construct123(Circle)
//or
construct123(Square)
Is it even possible?
The easiest would be to modify the signature of construct123 slightly
def construct123(figure: Double => Figure): Either[String, Figure] =
Right(figure(1.23))
construct123(Circle.apply) // Right(Circle(1.23))
construct123(Square.apply) // Right(Square(1.23))
construct123(Circle(_)) // Right(Circle(1.23))
construct123(Square(_)) // Right(Square(1.23))
construct123(Circle) // Right(Circle(1.23))
construct123(Square) // Right(Square(1.23))
Or construct123 can be written as a higher-order function
val construct123: (Double => Figure) => Either[String, Figure] =
figure => Right(figure(1.23))
Difference between method and function in Scala
Circle and Square in construct123(Circle) and construct123(Square) are not the case classes Circle and Square but their companion objects
Class companion object vs. case class itself
So actually you want to transform an object into an instance of its companion class. You can do this for example with a macro
// libraryDependencies += scalaOrganization.value % "scala-reflect" % scalaVersion.value
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
def construct123[A](figure: A): Either[String, Figure] = macro construct123Impl[A]
def construct123Impl[A: c.WeakTypeTag](c: blackbox.Context)(figure: c.Tree): c.Tree = {
import c.universe._
val companionClass = weakTypeOf[A].companion
q"_root_.scala.Right.apply(new $companionClass(1.23))" // using constructor of the case class
}
or
def construct123Impl[A: c.WeakTypeTag](c: blackbox.Context)(figure: c.Tree): c.Tree = {
import c.universe._
val A = symbolOf[A].asClass.module
q"_root_.scala.Right.apply($A.apply(1.23))" // using apply method of the companion object
}
Testing (in a different subproject):
construct123(Circle) // Right(Circle(1.23))
construct123(Square) // Right(Square(1.23))
// scalacOptions += "-Ymacro-debug-lite"
//scalac: scala.Right.apply(new Macros.Figure.Circle(1.23))
//scalac: scala.Right.apply(new Macros.Figure.Square(1.23))
//scalac: scala.Right.apply(Circle.apply(1.23))
//scalac: scala.Right.apply(Square.apply(1.23))
You can hide the work with macros in type classes (defined with whitebox implicit macros). The type class ToCompanion below is similar to HasCompanion in Get companion object of class by given generic type Scala (answer). The type class Generic from Shapeless (used below to define construct123) is also macro-generated. Some intros to type classes (ordinary, not macro-generated): 1 2 3 4 5 6 7 8 9
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
// type class
trait ToCompanion[A] {
type Out
}
object ToCompanion {
type Aux[A, Out0] = ToCompanion[A] {type Out = Out0}
// materializer
def apply[A](implicit tcc: ToCompanion[A]): ToCompanion.Aux[A, tcc.Out] = tcc
// def apply[A](implicit tcc: ToCompanion[A]): tcc.type = tcc
// instance of the type class
implicit def mkToCompanion[A, B]: ToCompanion.Aux[A, B] = macro mkToCompanionImpl[A]
// implicit def mkToCompanion[A]: ToCompanion[A] = macro mkToCompanionImpl[A] // then implicitly[ToCompanion.Aux[Circle, Circle.type]] doesn't compile in spite of white-boxity
def mkToCompanionImpl[A: c.WeakTypeTag](c: whitebox.Context): c.Tree = {
import c.universe._
val A = weakTypeOf[A]
val companion = A.companion
val ToCompanion = weakTypeOf[ToCompanion[A]]
q"new $ToCompanion { type Out = $companion }"
}
}
implicitly[ToCompanion.Aux[Circle, Circle.type]] // compiles
implicitly[ToCompanion.Aux[Circle.type, Circle]] // compiles
val tc = ToCompanion[Circle.type]
implicitly[tc.Out =:= Circle] // compiles
val tc1 = ToCompanion[Circle]
implicitly[tc1.Out =:= Circle.type] // compiles
// libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.10"
import shapeless.{::, Generic, HNil}
def construct123[A, B <: Figure](figure: A)(implicit
toCompanion: ToCompanion.Aux[A, B],
generic: Generic.Aux[B, Double :: HNil]
): Either[String, Figure] = Right(generic.from(1.23 :: HNil))
construct123(Circle) // Right(Circle(1.23))
construct123(Square) // Right(Square(1.23))
Since all the classes are now known at compile time it's better to use compile-time reflection (the above macros). But in principle runtime reflection can be used too
import scala.reflect.runtime.{currentMirror => rm}
import scala.reflect.runtime.universe._
def construct123[A: TypeTag](figure: A): Either[String, Figure] = {
val classSymbol = symbolOf[A].companion.asClass
//val classSymbol = typeOf[A].companion.typeSymbol.asClass
val constructorSymbol = typeOf[A].companion.decl(termNames.CONSTRUCTOR).asMethod
val res = rm.reflectClass(classSymbol).reflectConstructor(constructorSymbol)(1.23).asInstanceOf[Figure]
Right(res)
}
or
import scala.reflect.ClassTag
import scala.reflect.runtime.{currentMirror => rm}
import scala.reflect.runtime.universe._
def construct123[A: TypeTag : ClassTag](figure: A): Either[String, Figure] = {
val methodSymbol = typeOf[A].decl(TermName("apply")).asMethod
val res = rm.reflect(figure).reflectMethod(methodSymbol).apply(1.23).asInstanceOf[Figure]
Right(res)
}
Or you can use structural types aka duck typing (i.e. also runtime reflection under the hood)
import scala.language.reflectiveCalls
def construct123(figure: { def apply(x: Double): Figure }): Either[String, Figure] =
Right(figure(1.23))
How can I make this work?
def getSingleton[T <: scala.Singleton]: T = {
???
}
object X
val x = getSingleton[X.type]
Or similar, appreciate the signature may need to change slightly.
In Scala 2.13 there is built-in type class ValueOf 1 2 3
def getSingleton[T <: Singleton](implicit valueOf: ValueOf[T]): T = valueOf.value
In Scala 2.12 you can use type class Witness from Shapeless 1 2
// libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.10"
import shapeless.Witness
def getSingleton[T <: Singleton](implicit witness: Witness.Aux[T]): T = witness.value
Or if you prefer not to depend on Shapeless you can write a macro
// libraryDependencies += scalaOrganization.value % "scala-reflect" % scalaVersion.value
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
def getSingleton[T <: Singleton]: T = macro getSingletonImpl[T]
def getSingletonImpl[T <: Singleton : c.WeakTypeTag](c: blackbox.Context): c.Tree = {
import c.universe._
// q"${weakTypeOf[T].typeSymbol.name.toTermName}"
// q"${weakTypeOf[T].dealias.typeSymbol.asClass.module}" // dealiased version
q"${symbolOf[T].asClass.module}" // not dealiased version
}
All the above works at compile time. If it's enough to get the value at runtime you can use Scala runtime reflection with TypeTag
import scala.reflect.runtime.{currentMirror => rm}
import scala.reflect.runtime.universe._
def getSingleton[T: TypeTag]: T =
rm.reflectModule(symbolOf[T].asClass.module.asModule).instance.asInstanceOf[T]
or with ClassTag
import scala.reflect.{ClassTag, classTag}
def getSingleton[T: ClassTag]: T =
rm.reflectModule(rm.moduleSymbol(classTag[T].runtimeClass)).instance.asInstanceOf[T]
or if you prefer not to depend on scala-reflect you can use Java reflection
def getSingleton[T: ClassTag]: T =
classTag[T].runtimeClass.getField("MODULE$").get(null).asInstanceOf[T]
In scala, is it possible to initialise a singleton object from a TypeTag?
Get the module symbol, given I have the module class, scala macro
Get instance of singleton type in scala
Scala object import in runtime
Is it possible pass generic parameter using class:
def m(clazz: Class[_]): Unit = {
m2[] //here I want to exact type (that I should have because I have Class)
}
def m2[C: ClassTag]() : List[C] = {
println("hi")
List.empty
}
Any Ideas?
IIUC you want to call a method that requires a ClassTag while all you have is a Class. You can create a ClassTag from a Class like this:
def m(clazz: Class[_]): Unit = {
m2()(ClassTag(clazz))
}
ClassTags (as well as TypeTags and WeakTypeTags) are for persisting some compile-time information till runtime. You want to do something in reverse direction. You want, having runtime information (clazz: Class[_]), to do something at compile time (specify type parameter C of m2). So ClassTags are irrelevant.
You can call compiler at runtime
import scala.tools.reflect.ToolBox
import scala.reflect.runtime.currentMirror
object App {
val tb = currentMirror.mkToolBox()
def m(clazz: Class[_]): Unit = {
tb.eval(tb.parse(s"import App._; m2[${clazz.getName}]"))
}
def m2[C]() : List[C] = {
println("hi")
List.empty
}
def main(args: Array[String]): Unit = {
m(classOf[String]) //hi
}
}
libraryDependencies ++= Seq(
scalaOrganization.value % "scala-reflect" % scalaVersion.value,
scalaOrganization.value % "scala-compiler" % scalaVersion.value,
)
I have created a Workflow Processor Trait similar to the one mentioned below:
import org.scalatestplus.play._
import play.api.mvc._
import play.api.test._
import play.api.test.Helpers._
import org.scalatest.Matchers._
import org.scalamock.scalatest.MockFactory
import utils.OAuthUtils._
import utils.OAuthUtils
import utils.OAuthProcess
import play.api.Application
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import play.api.libs.json.JsResult
import play.api.libs.json.Json
import play.api.libs.json.JsSuccess
import play.api.libs.json.JsError
import play.api.libs.ws.WS
trait MyProcess[A] {
type B
type C
type D
def stage1(s: String): B
def stage2(b: B)(implicit e: ExecutionContext, app: Application, a: A): Future[C]
def stage3(c: C)(implicit e: ExecutionContext, app: Application, a: A): Future[JsResult[D]]
def process(s: String)(implicit e: ExecutionContext, app: Application, a: A): Future[JsResult[D]] = {
val b = stage1(s)
val f_d = for {
c <- stage2(b)
d <- stage3(c)
} yield d
f_d
}
}
Now I would like to Unit test this code. So I created a nicer little scalatest scalamock test suite:
class TestController extends PlaySpec with Results with MockFactory {
"MyController" must {
" testing for method process" in {
running(FakeApplication()) {
implicit val context = scala.concurrent.ExecutionContext.Implicits.global
implicit val s = "implicit String"
implicit val currentApp = play.api.Play.current
case class TestParms(s: String)
abstract class TestProcessor extends MyProcess[TestParms] {
type B = String
type C = String
type D = String
}
implicit val t = stub[TestProcessor]
t.stage1(_: String).when(token).returns(testToken)
(t.stage2(_: String)(_: ExecutionContext, _: Application, _: TestParms)).when(token, context, currentApp, tp).returns({
Future.successful(stage2String)
})
(t.stage3(_: String)(_: ExecutionContext, _: Application, _: TestParms)).when(token, context, currentApp, tp).returns({
Future.successful(Json.fromJson[String](Json.parse(stage3String)))
})
}
}
}
}
My expectation is to set this stub on a different class and test the class. Stubs (t.stage2 and t.stage3) compile fine but the following statement doesn't compile.
t.stage1(_: String).when(token).returns(testToken)
Compiler reports the following issue:
overloaded method value when with alternatives: (resultOfAfterWordApplication: org.scalatest.words.ResultOfAfterWordApplication)Unit <and> (f: => Unit)Unit cannot be applied to (String) TestController.scala /play-scala/test/controllers
Could someone help? I am finding it very difficult to write Unit tests for Scala classes as well as mocking them.
Scalatest versions from Build.sbt:
"org.scalatestplus" %% "play" % "1.2.0" % "test",
"org.scalamock" %% "scalamock-scalatest-support" % "3.2" % "test",
Try wrapping the invocation in parens
(t.stage1(_: String)).when(token).returns(testToken)
I believe scalac thinks you're trying to call when on an instance of String (since that would be what's returned by t.stage1(_)).
On version:
"org.typelevel" %% "scodec-core" % "1.5.0"
I'm trying to use coproduct functionality, as shown in the test case demonstrate fixing the codec to a known subtype.
I keep getting the error: "could not find implicit value for parameter auto: scodec.codecs.CoproductBuilderAuto[my.class.here]"
I even copy pasted the example and could not get it to work:
import scalaz.\/
import shapeless._
import scodec.bits._
import scodec.codecs._
import scodec._
sealed trait Sprocket
object Sprocket {
implicit val discriminated: Discriminated[Sprocket, Int] = Discriminated(uint8)
}
def codec(d: Int): Codec[Sprocket] = Codec.coproduct[Sprocket].discriminatedBy(provide(d)).auto
I'll continue to look into this on my end, but was wondering if there was an issue fixed around this lately. I cloned the repo, and it worked from the clone - but not when I use the released version.
The error from the example code is caused by not having any subtypes of Sprocket defined. If there's at least 1 subtype of Sprocket, then Shapeless is able to generate a LabelledGeneric[Sprocket] instance where the representation is a discriminated union. The union is a coproduct of labelled subtypes.
Adding the following resolves the error:
case class Woozle(x: Int, y: Int) extends Sprocket
object Woozle {
implicit val discriminator: Discriminator[Sprocket, Woozle, Int] = Discriminator(1)
implicit val codec: Codec[Woozle] = (uint8 :: uint8).as[Woozle]
}
Note that you need both the discriminator and the codec implicits in the companion. If the discriminator isn't defined, you'll get the reported error. If the codec isn't defined, you'll get a diverging implicit error. Theoretically, the Woozle codec could be automatically derived if there's an implicit Codec[Int] in scope, but scalac isn't up to the task -- instead, it bails out with a diverging implicit expansion error. We hope to improve this with Shapeless 2.1.
For reference, full source:
import scalaz.\/
import shapeless._
import scodec.bits._
import scodec.codecs._
import scodec._
sealed trait Sprocket
object Sprocket {
implicit val discriminated: Discriminated[Sprocket, Int] = Discriminated(uint8)
}
case class Woozle(x: Int, y: Int) extends Sprocket
object Woozle {
implicit val discriminator: Discriminator[Sprocket, Woozle, Int] = Discriminator(1)
implicit val codec: Codec[Woozle] = (uint8 :: uint8).as[Woozle]
}
object Main extends App {
def codec(d: Int): Codec[Sprocket] = Codec.coproduct[Sprocket].discriminatedBy(provide(d)).auto
}
And build:
scalaVersion := "2.11.4"
libraryDependencies += "org.typelevel" %% "scodec-core" % "1.5.0"