Get the module symbol, given I have the module class, scala macro - scala

I'm trying to build a simple typeclass IsEnum[T] using a macro.
I use knownDirectSubclasses to get all the direct subclasses if T, ensure T is a sealed trait, and that all subclasses are of case objects (using subSymbol.asClass.isModuleClass && subSymbol.asClass.isCaseClass).
Now I'm trying to build a Seq with the case objects referred by the subclasses.
It's working, using a workaround:
Ident(subSymbol.asInstanceOf[scala.reflect.internal.Symbols#Symbol].sourceModule.asInstanceOf[Symbol])
But I copied that from some other question, yet it seems hacky and wrong. Why does that work? and is there a cleaner way to achieve that?

In 2.13 you can materialize scala.ValueOf
val instanceTree = c.inferImplicitValue(appliedType(typeOf[ValueOf[_]].typeConstructor, subSymbol.asClass.toType))
q"$instanceTree.value"
Tree will be different
sealed trait A
object A {
case object B extends A
case object C extends A
}
//scalac: Seq(new scala.ValueOf(A.this.B).value, new scala.ValueOf(A.this.C).value)
but at runtime it's still Seq(B, C).
In 2.12 shapeless.Witness can be used instead of ValueOf
val instanceTree = c.inferImplicitValue(appliedType(typeOf[Witness.Aux[_]].typeConstructor, subSymbol.asClass.toType))
q"$instanceTree.value"
//scalac: Seq(Witness.mkWitness[App.A.B.type](A.this.B.asInstanceOf[App.A.B.type]).value, Witness.mkWitness[App.A.C.type](A.this.C.asInstanceOf[App.A.C.type]).value)
libraryDependencies += "com.chuusai" %% "shapeless" % "2.4.0-M1" // in 2.3.3 it doesn't work
In Shapeless they use kind of
subSymbol.asClass.toType match {
case ref # TypeRef(_, sym, _) if sym.isModuleClass => mkAttributedQualifier(ref)
}
https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/singletons.scala#L230
or in our case simply
mkAttributedQualifier(subSymbol.asClass.toType)
but their mkAttributedQualifier also uses downcasting to compiler internals and the tree obtained is like Seq(A.this.B, A.this.C).
Also
Ident(subSymbol.companionSymbol)
seems to work (tree is Seq(B, C)) but .companionSymbol is deprecated (in scaladocs it's written "may return unexpected results for module classes" i.e. for objects).
Following approach similar to the one used by #MateuszKubuszok in his library enumz you can try also
val objectName = symbol.fullName
c.typecheck(c.parse(s"$objectName"))
and the tree is Seq(App.A.B, App.A.C).
Finally, if you're interested in the tree Seq(B, C) (and not some more complicated tree) it seems you can replace
Ident(subSymbol.asInstanceOf[scala.reflect.internal.Symbols#Symbol].sourceModule.asInstanceOf[Symbol/*ModuleSymbol*/])
with more conventional
Ident(subSymbol.owner.info.decl(subSymbol.name.toTermName)/*.asModule*/)
or (the shortest option)
Ident(subSymbol.asClass.module/*.asModule*/)

Related

In scala, is it possible to discourage the compiler from searching for Predef implicit first?

This post:
Where does Scala look for implicits?
described the implicit search precedence & algorithm used by modern scala compiler. In the above list, directly imported implicit functions should have higher precedence over scopes in associated types (e.g. defined in companion object)
This rule make sense most of the time, until the directly imported Predef.scala start to interfere:
case class A(v: Int)
object A {
implicit class AFns(self: A) {
def +(v2: Int): A = A(self.v + v2)
}
}
val a1 = A(3)
val b = a1 + 4
assert(b == A(7))
The above example should compile successfully, but + operator override for ALL classes defined in Predef dominated the scene and caused all extensions with + operator to be useless (unless explicitly imported in a tighter scope). This is seriously annoying, is there a way to disable implicits in Predef or 'downgrade' its precedence?
The above experiment has been conducted in scala 2.12.12 & 2.13.3
Importing A._ explicitly works, but you can also use -Yimports by adding this to your build.sbt to leave out the scala.Predef._ import:
scalacOptions ++= Seq("-Yimports", "java.lang", "scala")
After that, you can import everything from Predef except the any2stringadd class:
import Predef.{any2stringadd => _, _}
Here's a Scastie.

'with' keyword usage in scala with case classes

I though if something like this makes sense in scala:
object CaseClassUnion extends App {
case class HttpConfig(bindUrl: String, port: String)
case class DbConfig(url: String, usr: String, pass: String)
val combined: HttpConfig with DbConfig = ???
//HttpConfig("0.0.0.0", "21") ++ DbConfig("localhost", "root", "root")
//would be nice to have something like that
}
At least this compiles... Is there a way, probably with macros magic to achieve union of two classes given their instances?
In zio I believe there is something like in reverse:
val live: ZLayer[ProfileConfiguration with Logging, Nothing, ApplicationConfiguration] =
ZLayer.fromServices[ProfileConfigurationModule.Service, Logger[String], Service] { (profileConfig, logger) => ???
where we convert ProfileConfiguration with Logging to function of ProfileConfigurationModule.Service, Logger[String] => Service
Several things.
When you have several traits combined with with Scala does a trait linearization to combine them into one class with a linear hierarchy. But that's true for traits which doesn't have constructors!
case class (which is not a trait) cannot be extended with another case class (at all) because that would break contracts like:
case class A(a: Int)
case class B(a: Int, b: String) extends A(a)
A(1) == B(1, "") // because B is A and their respective fields match
B(1, "") != A(1) // because A is not B
B(1, "").hashCode != A(1).hashCode // A == B is true but hashCodes are different!
which means that you cannot even generate case class combination manually. You want to "combine" them, use some product: a tuple, another case class, etc.
If you are curious about ZIO it:
uses traits
uses them as some sort of type-level trick to represent an unordered set of dependencies, where type inference would calculate set sum when you combine operations and some clever trickery to remove traits from the list using .provide to remove dependency from the set
ZLayers are just making these shenanigans easier
so and if you even pass there some A with B you either combined it yourself by using cake pattern, or you passed dependencies one by one. ZIO developer might never be faced with the problem of needing some macro to combine several case classes (.provide(combineMagically(A, B, C, D, ...)) as they could pass implementations of each dependency one by one (.provide(A).provide(B)) and the code underneath would never need the combination of these types as one value - it's just a compile-time trick that might never translate to the requirement of an actual value of type A with B with C with D ....
TL;DR: You cannot generate a combination of 2 case classes; ZIO uses compound types as some sort of type-level set to trace dependencies and it doesn't actually require creating values of the compound types.

Scala implicit conversion to monadic value within effectful macro

Edit: I updated the question to be more descriptive.
Note: I use the Scala 2.11 compiler, because that is the compiler version used by the LMS tutorial project.
I am porting a DSL written in Haskell to Scala. The DSL is an imperative language, so I used monads with do-notation, namely WriterT [Stmt] (State Label) a. I had trouble porting this to Scala, but worked around it by using the ReaderWriterState monad and just using Unit for the Reader component. I then went about searching for an alternative for the do-notation found in Haskell. For-comprehensions are supposed to be this alternative in Scala, but they are tailored towards sequences, I e.g. could not pattern match a tuple, it would insert a call to filter. So I started looking for alternatives and found multiple libraries: effectful, monadless, and each. I tried effectful first which does exactly what I wanted to achieve, I even prefer it over Haskell's do-notation, and it worked well with the ReaderWriterState monad from ScalaZ I had been using. In my DSL I have actions like Drop() (a case class) that I want to be able to use directly as a statement. I hoped to use implicits for this, but because the ! method of effectful (or monadless equivalent for that matter) is too general, I cannot get Scala to automatically convert my Action case classes to something of type Stmt (the ReaderWriterState that returns Unit).
So if not implicits, would there be a different way to achieve it?
As shown in Main.passes2, I did figure out a workaround that I would not mind using, but I am curious whether I stumbled upon is some limitation of the language, or is simply my lack of experience with Scala.
With Main.fails1 I will get the following error message: Implicit not found: scalaz.Unapply[scalaz.Monad, question.Label]. Unable to unapply type question.Label into atype constructor of kind M[_] that is classified by the type class scalaz.Monad. Check that the type class is defined by compiling implicitly[scalaz.Monad[type constructor]] and review the implicits in object Unapply, which only cover common type 'shapes.'
Which comes from ScalaZ its Unapply: https://github.com/scalaz/scalaz/blob/d2aba553e444f951adc847582226d617abae24da/core/src/main/scala/scalaz/Unapply.scala#L50
And with Main.fails2 I will just get: value ! is not a member of question.Label
I assume it is just a matter of writing the missing implicit definition, but I am not quite sure which one Scala wants me to write.
The most important bits of my build.sbt are the version:
scalaVersion := "2.11.2",
And the dependencies:
libraryDependencies += "org.scala-lang" % "scala-compiler" % "2.11.2",
libraryDependencies += "org.scala-lang" % "scala-library" % "2.11.2",
libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.11.2",
libraryDependencies += "org.pelotom" %% "effectful" % "1.0.1",
Here is the relevant code, containing the things I tried and the code necessary to run those things:
package question
import scalaz._
import Scalaz._
import effectful._
object DSL {
type GotoLabel = Int
type Expr[A] = ReaderWriterState[Unit, List[Action], GotoLabel, A]
type Stmt = Expr[Unit]
def runStmt(stmt: Stmt, startLabel: GotoLabel): (Action, GotoLabel) = {
val (actions, _, updatedLabel) = stmt.run(Unit, startLabel)
val action = actions match {
case List(action) => action
case _ => Seq(actions)
}
(action, updatedLabel)
}
def runStmt(stmt: Stmt): Action = runStmt(stmt, 0)._1
def getLabel(): Expr[GotoLabel] =
ReaderWriterState((_, label) => (Nil, label, label))
def setLabel(label: GotoLabel): Stmt =
ReaderWriterState((_, _) => (Nil, Unit, label))
implicit def actionStmt(action: Action): Stmt =
ReaderWriterState((_, label) => (List(action), Unit, label))
}
import DSL._
final case class Label(label: String) extends Action
final case class Goto(label: String) extends Action
final case class Seq(seq: List[Action]) extends Action
sealed trait Action {
def stmt(): Stmt = this
}
object Main {
def freshLabel(): Expr[String] = effectfully {
val label = getLabel.! + 1
setLabel(label).!
s"ants-$label"
}
def passes0() =
freshLabel()
.flatMap(before => Label(before))
.flatMap(_ => freshLabel())
.flatMap(after => Label(after));
def passes1() = effectfully {
unwrap(actionStmt(Label(unwrap(freshLabel()))))
unwrap(actionStmt(Label(unwrap(freshLabel()))))
}
def fails1() = effectfully {
unwrap(Label(unwrap(freshLabel())))
unwrap(Label(unwrap(freshLabel())))
}
def pasess2() = effectfully {
Label(freshLabel.!).stmt.!
Label(freshLabel.!).stmt.!
}
def fails2() = effectfully {
Label(freshLabel.!).!
Label(freshLabel.!).!
}
def main(args: Array[String]): Unit = {
runStmt(passes0())
}
}
Question quality
I want to start with complaining about the question quality. You provide almost no textual description of what you are trying to achieve and then just show us a wall of code but don't explicitly reference your dependencies. This is far from what could count as a Minimal, Complete, and Verifiable example. And typically you get much more chances to get some answers if you provide a clear problem that is easy to understand and reproduce.
Back to the business
When you write something like
unwrap(Label(unwrap(freshLabel())))
you ask too much from the Scala compiler. Particularly unwrap can unwrap only something that is wrapped into some Monad, but Label is not a monad. It is not just the fact that there is no Monad[Label] instance, it is the fact that it structurally doesn't fit that kills you. Simply speaking an instance of ScalaZ Unapply is an object that allows you to split an applied generic type MonadType[SpecificType] (or other FunctorType[SpecificType]) into an "unapplied"/"partially-applied" MonadType[_] and SpecificType even when (as in your case) MonadType[_] is actually something complicated like ReaderWriterState[Unit, List[Action], GotoLabel, _]. And so the error says that there is no known way to split Label into some MonadType[_] and SpecifictType. You probably expected that your implicit actionStmt would do the trick to auto-convert Label into a Statement but this step is too much for the Scala compiler because for it to work, it also implies splitting the composite type. Note that this conversion is far from obvious for the compiler as the unwrap is itself a generic method that can handle any Monad. Actually in some sense ScalaZ needs Unapply exactly because the compiler can't do such things automatically. Still if you help the compiler just a little bit by specifying generic type, it can do the rest of the work:
def fails1() = effectfully {
// fails
// unwrap(Label(unwrap(freshLabel())))
// unwrap(Label(unwrap(freshLabel())))
// works
unwrap[Stmt](Label(unwrap(freshLabel())))
unwrap[Stmt](Label(unwrap(freshLabel())))
}
There is also another possible solution but it is a quite dirty hack: you can roll out your custom Unapply to persuade the compiler that Label is actually the same as Expr[Unit] which can be split as Expr[_] and Unit:
implicit def unapplyAction[AC <: Action](implicit TC0: Monad[Expr]): Unapply[Monad, AC] {
type M[X] = Expr[X]
type A = Unit
} = new Unapply[Monad, AC] {
override type M[X] = Expr[X]
override type A = Unit
override def TC: Monad[Expr] = TC0
// This can't be implemented because Leibniz really witness only exactly the same types rather than some kind of isomorphism
// Luckily effectful doesn't use leibniz implementation
override def leibniz: AC === Expr[Unit] = ???
}
The obvious reason why this is a dirty hack is that Label is actually not the same as Expr[Unit] and you can see it by the fact that you can't implement leibniz in your Unapply. Anyway, if you import unapplyAction, even your original fails1 will compile and work because effectful doesn't use leibniz inside.
As for your fails2, I don't think you can make it work in any simple way. Probably the only way that you may try is to create another macro that would convert in-place call to ! on your action (or its implicit wrapper) into the effectful's ! on the action.stmt. This might work but I didn't try it.

Why do you need Arbitraries in scalacheck?

I wonder why Arbitrary is needed because automated property testing requires property definition, like
val prop = forAll(v: T => check that property holds for v)
and value v generator. The user guide says that you can create custom generators for custom types (a generator for trees is exemplified). Yet, it does not explain why do you need arbitraries on top of that.
Here is a piece of manual
implicit lazy val arbBool: Arbitrary[Boolean] = Arbitrary(oneOf(true, false))
To get support for your own type T you need to define an implicit def
or val of type Arbitrary[T]. Use the factory method Arbitrary(...) to
create the Arbitrary instance. This method takes one parameter of type
Gen[T] and returns an instance of Arbitrary[T].
It clearly says that we need Arbitrary on top of Gen. Justification for arbitrary is not satisfactory, though
The arbitrary generator is the generator used by ScalaCheck when it
generates values for property parameters.
IMO, to use the generators, you need to import them rather than wrapping them into arbitraries! Otherwise, one can argue that we need to wrap arbitraries also into something else to make them usable (and so on ad infinitum wrapping the wrappers endlessly).
You can also explain how does arbitrary[Int] convert argument type into generator. It is very curious and I feel that these are related questions.
forAll { v: T => ... } is implemented with the help of Scala implicits. That means that the generator for the type T is found implicitly instead of being explicitly specified by the caller.
Scala implicits are convenient, but they can also be troublesome if you're not sure what implicit values or conversions currently are in scope. By using a specific type (Arbitrary) for doing implicit lookups, ScalaCheck tries to constrain the negative impacts of using implicits (this use also makes it similar to Haskell typeclasses that are familiar for some users).
So, you are entirely correct that Arbitrary is not really needed. The same effect could have been achieved through implicit Gen[T] values, arguably with a bit more implicit scoping confusion.
As an end-user, you should think of Arbitrary[T] as the default generator for the type T. You can (through scoping) define and use multiple Arbitrary[T] instances, but I wouldn't recommend it. Instead, just skip Arbitrary and specify your generators explicitly:
val myGen1: Gen[T] = ...
val mygen2: Gen[T] = ...
val prop1 = forAll(myGen1) { t => ... }
val prop2 = forAll(myGen2) { t => ... }
arbitrary[Int] works just like forAll { n: Int => ... }, it just looks up the implicit Arbitrary[Int] instance and uses its generator. The implementation is simple:
def arbitrary[T](implicit a: Arbitrary[T]): Gen[T] = a.arbitrary
The implementation of Arbitrary might also be helpful here:
sealed abstract class Arbitrary[T] {
val arbitrary: Gen[T]
}
ScalaCheck has been ported from the Haskell QuickCheck library. In Haskell type-classes only allow one instance for a given type, forcing you into this sort of separation.
In Scala though, there isn't such a constraint and it would be possible to simplify the library. My guess is that, ScalaCheck being (initially written as) a 1-1 mapping of QuickCheck, makes it easier for Haskellers to jump into Scala :)
Here is the Haskell definition of Arbitrary
class Arbitrary a where
-- | A generator for values of the given type.
arbitrary :: Gen a
And Gen
newtype Gen a
As you can see they have a very different semantic, Arbitrary being a type class, and Gen a wrapper with a bunch of combinators to build them.
I agree that the argument of "limiting the scope through semantic" is a bit vague and does not seem to be taken seriously when it comes to organizing the code: the Arbitrary class sometimes simply delegates to Gen instances as in
/** Arbirtrary instance of Calendar */
implicit lazy val arbCalendar: Arbitrary[java.util.Calendar] =
Arbitrary(Gen.calendar)
and sometimes defines its own generator
/** Arbitrary BigInt */
implicit lazy val arbBigInt: Arbitrary[BigInt] = {
val long: Gen[Long] =
Gen.choose(Long.MinValue, Long.MaxValue).map(x => if (x == 0) 1L else x)
val gen1: Gen[BigInt] = for { x <- long } yield BigInt(x)
/* ... */
Arbitrary(frequency((5, gen0), (5, gen1), (4, gen2), (3, gen3), (2, gen4)))
}
So in effect this leads to code duplication (each default Gen being mirrored by an Arbitrary) and some confusion (why isn't Arbitrary[BigInt] not wrapping a default Gen[BigInt]?).
My reading of that is that you might need to have multiple instances of Gen, so Arbitrary is used to "flag" the one that you want ScalaCheck to use?

Scala pattern matching in the for construct

I have the following data model which I'm going to do pattern matching against later:
abstract class A
case class C(s:String) extends A
abstract class B extends A
case class D(i:Int) extends B
case class E(s:Int, e:Int) extends B
A is the abstract super type of the hierarchy. C is a concrete subclass of A. Other concrete subclasses of A are subclasses of B which is in turn a subclass of A.
Now if I write something like this, it works:
def match(a:A) a match {
a:C => println("C")
a:B => println("B")
}
However, in a for loop I cannot match against B. I assume that I need a constructor pattern, but since B is abstract, there is no constructor pattern for B.
val list:List[A] = List(C("a"), D(1), E(2,5), ...)
for (b:B <- list) println(b) // Compile error
for (b#B <- list) println(b) // Compile error
Here, I would like to print only B instances. Any workaround for this case?
You can use collect:
list.collect { case b: B => println(b) }
If you want to better undertand this, I recommend to read about partial functions. Here for example.
Sergey is right; you'll have to give up for if you want to pattern match and filter only B instances. If you still want to use a for comprehension for whatever reason, I think one way is to just resort to using a guard:
for (b <- list if b.isInstanceOf[B]) println(b)
But it's always best to pick pattern-matching instead of isInstanceOf. So I'd go with the collect suggestion (if it made sense in the context of the rest of my code).
Another suggestion would be to define a companion object to B with the same name, and define the unapply method:
abstract class A
case class C(s:String) extends A
abstract class B extends A
object B { def unapply(b: B) = Option(b) } // Added a companion to B
case class D(i:Int) extends B
case class E(s:Int, e:Int) extends B
Then you can do this:
for (B(b) <- list) println(b)
So that's not the 'constructor' of B, but the companion's unapply method.
It works, and that's what friends are for, right?
(See http://www.scala-lang.org/node/112 )
If you ask me, the fact that you can't use pattern matching here is an unfortunate inconsistency of scala. Indeed scala does let you pattern match in for comprehensions, as this example will show:
val list:List[A] = List(C("a"), D(1), E(2,5)
for ((b:B,_) <- list.map(_ -> null)) println(b)
Here I temporarily wrap the elements into pairs (whith a dummy and unused second value) and then pattern match for a pair where the first element is of type B. As the output shows, you get the expected behaviour:
D(1)
E(2,5)
So there you go, scala does support filtering based on pattern matching (even when matching by type), it just seems that the grammar does not handle pattern matching a single element by type.
Obviously I am not advising to use this trick, this was just to illustrate. Using collect is certainly better.
Then again, there is another, more general solution if for some reason you really fancy for comprehensions more than anything:
object Value {
def unapply[T]( value: T ) = Some( value )
}
for ( Value(b:B) <- list ) println(b)
We just introduced a dummy extractor in the Value object which just does nothing, so that Value(b:B) has the same meaning as just b:B, except that the former does compile. And unlike my earlier trick with pairs, it is relatively readable, and Value only has to be written once, you can use it at will then (in particular, no need for writing a new extractor for each type you want to pattern match against, as in #Faiz's answer. I'll let you find a better name than Value though.
Finally, there is another work around that works out of the box (credit goes to Daniel Sobral), but is slightly less readable and requires a dummy identifier (here foo):
for ( b #(foo:B) <- list ) println(b)
// or similarly:
for ( foo #(b:B) <- list ) println(b)
my 2 cents: You can add a condition in the for comprehension checking type but that would NOT be as elegant as using collect which would take only instances of class B.