Can I introduce an implicit precedence relation between packages as with objects? - scala

I was wondering how to place effectively the same implicit conversion in more than one package in such a way that importing the contents of one is enough, but importing all doesn't introduce conflicts. Regardless of what's your opinion about the idea as stated (I can guess), it's almost possible:
trait syntax
object syntax {
implicit class syntaxIntExtension(a :Int) {
def times2 = a * 2
def times3 = a * 3
}
}
trait extension extends syntax
object extension {
implicit class dialectIntExtension(a :Int) extends syntax.syntaxIntExtension(a) {
override def times2 = a + a
def times4 = a.times2.times2
}
}
object lazyUser {
import syntax._
import extension._
1.times2
1.times3
1.times4
}
The caveat here is that the scopes syntax and extension must be objects; package objects won't work, and I have absolutely no idea what I could even try in Scala 3. Can I somehow use syntax and expansion identifiers as normal scopes, containing normal 'non inner' classes? The only ways I can think of is
to have syntaximpl and extensionimpl, and fill syntax and extension up to the brim with type aliases and vals. Me not like.
declare everything I want as inner types of some wrapper traits and compose syntax and extension by mixing in a long list of such wrappers. Ugh.
Now, I can make it work relying solely on the other implicit precedence rule of being 'more specific than', but it comes with some drawbacks, such as the need for Scala 2 style pseudo extension methods even in Scala 3. I wonder thus if there is something I haven't thought about when trying to exploit the former rule.

Related

scala even type number

The only way I can think of doing this, without creating a wrapper class, is to use scala 3's type unions like this
type Even = 0 | 2 | 4 | 6 | 8
val even : Even = 4
but that obviously has a limit. Is there a way to create the "entire" range?
As a follow up, what about for other ranges? Is there some way to create a function that restricts the type in some arbitrary way (as dangerous as that sounds)?
You can create a newtype with a smart constructor. Several ways to do it.
First, manually, to show how it work:
trait Newtype[T] {
type Type
protected def wrap(t: T): Type = t.asInstanceOf[Type]
protected def unwrap(t: Type): T = t.asInstanceOf[T]
}
type Even = Even.Type
object Even extends Newtype[Int] {
def parse(i: Int): Either[String, Even] =
if (i % 2 == 0) Right(wrap(i))
else Left(s"$i is odd")
implicit class EvenOps(private val even: Even) extends AnyVal {
def value: Int = unwrap(even)
def +(other: Even): Even = wrap(even.value + other.value)
def -(other: Even): Even = wrap(even.value - other.value)
}
}
You are creating type Even which compiler knows nothing about, so it cannot prove that an arbitrary value is its instance. But you can force-cast to it an back again - if JVM in runtime won't be able to catch some issue with it, there is not problem (and since it assumes nothing about Even it cannot disprove anything by contradiction).
Since Even resolves to Even.Type - that is type Type within Even object - Scala's implicit scope will automatically fetch all implicits that are defined in object Even, so you can place your extension methods and typeclasses there.
This will help you pretend that this type has some methods defined.
In Scala 3 you can achieve the same with opaque type. However this representation, has the nice side that it is easy to make it cross compilable with Scala 2 and Scala 3. As a matter of the fast, that's what Monix Newtype did, so you can use it instead of implementing this functionality yourself.
import monix.newtypes._
type Even = Even.Type
object Even extends Newtype[Int] {
// ...
}
Another option is older macro-annotation based library Scala Newtype. It will take your type defined as case class and rewrite the code to implement something similar to what we have above:
import io.estatico.newtype.macros.newtype
#newtype case class Even(value: Int)
however it is harder to add your own smart constructor there, which is why it usually is paired with Refined Types. Then your code would look like:
import eu.timepit.refined._
import eu.timepit.refined.api.Refined
import eu.timepit.refined.numeric
import io.estatico.newtype.macros.newtype
#newtype case class Even(value: Int Refined numeric.Even)
object Even {
def parse(i: Int): Either[String, Even] =
refineV[numeric.Even](i).map(Even(_))
}
However, you might want to just use the plain refined type at this point, since Even newtype wouldn't introduce any domain knowledge beyond what refinement does.

Does Scala's Vector add any new methods on top of those provided by Seq and other superclasses?

Are there any methods in Scala's Vector that are not declared by its superclasses like AbstractSeq?
I am working on providing language localization (translation) for a learning environment/IDE built on top of Scala called Kojo (see kojo.in). I have translated most commonly used methods of Seq. Vector inherits them automatically, so I don't need to duplicated the translation code (keeping DRY). E.g.,
implicit class TurkishTranslationsForSeqMethods[T](s: Seq[T]) {
def başı: T = s.head
def kuyruğu: Seq[T] = s.tail
def boyu: Int = s.length
def boşMu: Boolean = s.isEmpty
// ...
}
implicit class TranslationsForVectorMethods[T](v: Vector[T]) {
??? // what to translate here?
}
Hence the question. Maybe, more importantly, is there a way to find out such novel additions for any class without having to do a manual diff?
The scaladoc provides a way to filter methods to not see the ones inherited from Seq for instance: https://www.scala-lang.org/api/current/scala/collection/immutable/Vector.html a'd click on "Filter all members".
Or, probably easier, IDEs usually provide a "Hierarchy" view of a class and its methods that would give you the information quickly.

How to create a Scala function that can parametrically create instances of sub-types of some type

Sorry I'm not very familiar with Scala, but I'm curious if this is possible and haven't been able to figure out how.
Basically, I want to create some convenience initializers that can generate a random sample of data (in this case a grid). The grid will always be filled with instances of a particular type (in this case a Location). But in different cases I might want grids filled with different subtypes of Location, e.g. Farm or City.
In Python, this would be trivial:
def fillCollection(klass, size):
return [klass() for _ in range(size)]
class City: pass
cities = fillCollection(City, 10)
I tried to do something similar in Scala but it does not work:
def fillGrid[T <: Location](size): Vector[T] = {
Vector.fill[T](size, size) {
T()
}
}
The compiler just says "not found: value T"
So, it it possible to approximate the above Python code in Scala? If not, what's the recommended way to handle this kind of situation? I could write an initializer for each subtype, but in my real code there's a decent amount of boilerplate overlap between them so I'd like to share code if possible.
The best workaround I've come up with so far is to pass a closure into the initializer (which seems to be how the fill method on Vectors already works), e.g.:
def fillGrid[T <: Location](withElem: => T, size: Int = 100): Vector[T] = {
Vector.fill[T](n1 = size, n2 = size)(withElem)
}
That's not a huge inconvenience, but it makes me curious why Scala doesn't support the "simpler" Python-style construct (if it in fact doesn't). I sort of get why having a "fully generic" initializer could cause trouble, but in this case I can't see what the harm would be generically initializing instances that are all known to be subtypes of a given parent type.
You are correct, in that what you have is probably the simplest option. The reason Scala can't do things the pythonic way is because the type system is much stronger, and it has to contend with type erasure. Scala can not guarantee at compile time that any subclass of Location has a particular constructor, and it will only allow you to do things that it can guarantee will conform to the types (unless you do tricky things with reflection).
If you want to clean it up a little bit, you can make it work more like python by using implicits.
implicit def emptyFarm(): Farm = new Farm
implicit def emptyCity(): City = new City
def fillGrid[T <: Location](size: Int = 100)(implicit withElem: () => T): Vector[Vector[T]] = {
Vector.fill[T](n1 = size, n2 = size)(withElem())
}
fillGrid[farm](3)
To make this more usable in a library, it's common to put the implicits in a companion object of Location, so they can all be brought into scope where appropriate.
sealed trait Location
...
object Location
{
implicit def emptyFarm...
implicit def emptyCity...
}
...
import Location._
fillGrid[Farm](3)
You can use reflection to accomplish what you want...
This is a simple example that will only work if all your subclasses have a zero args constructor.
sealed trait Location
class Farm extends Location
class City extends Location
def fillGrid[T <: Location](size: Int)(implicit TTag: scala.reflect.ClassTag[T]): Vector[Vector[T]] = {
val TClass = TTag.runtimeClass
Vector.fill[T](size, size) { TClass.newInstance().asInstanceOf[T] }
}
However, I have never been a fan of runtime reflection, and I hope there could be another way.
Scala cannot do this kind of thing directly because it's not type safe. It will not work if you pass a class without a zero-argument constructor. The Python version throws an error at runtime if you try to do this.
The closure is probably the best way to go.

How to pass around string values type-safely?

E.g.:
def updateAsinRecords(asins:Seq[String], recordType:String)
Above method takes a Seq of ASINs and a record type. Both have type of String. There are also other values that are passed around with type String in the application. Needless to say, this being Scala, I'd like to use the type system to my advantage. How to pass around string values in a type safe manner (like below)?
def updateAsinRecords(asins:Seq[ASIN], recordType:RecordType)
^ ^
I can imagine, having something like this:
trait ASIN { val value:String }
but I'm wondering if there's a better approach...
There is an excellent bit of new Scala functionality know as Value Classes and Universal Traits. They impose no runtime overhead but you can use them to work in a type safe manner:
class AnsiString(val inner: String) extends AnyVal
class Record(val inner: String) extends AnyVal
def updateAnsiRecords(ansi: Seq[AnsiString], record: Record)
They were created specifically for this purpose.
You could add thin wrappers with case classes:
case class ASIN(asin: String)
case class RecordType(recordType: String)
def updateAsinRecords(asins: Seq[ASIN], recordType: RecordType) = ???
updateAsinRecords(Vector(ASIN("a"), ASIN("b")), RecordType("c"))
This will not only make your code safer, but it will also make it much easier to read! The other big advantage of this approach is that refactoring later will be much easier. For example, if you decide later that an ASIN should have two fields instead of just one, then you just update the ASIN class definition instead of every place it's used. Likewise, you can do things like add methods to these types whenever you decide you need them.
In addition to the suggestions about using a Value Class / extends AnyVal, you should probably control the construction to allow only valid instances, since presumably not any old string is a valid ASIN. (And... is that an Amazon thing? It rings a bell somehow.)
The best way to do this is to make the constructor private and put a validating factory method in a companion object. The reason for this is that throwing exceptions in constructors (when an attempt is made to instantiate with an invalid argument) can lead to puzzling failure modes (I often see it manifest as a NoClassDefFoundError error when trying to load a different class).
So, in addition to:
case class ASIN private (asin: String) extends AnyVal { /* other stuff */ }
You should include something like this:
object A {
import scala.util.{Try, Success, Failure}
def fromString(str: String): Try[ASIN] =
if (validASIN(str))
Success(new ASIN(str))
else
Failure(new InvalidArgumentException(s"Invalid ASIN string: $str")
}
How about a type alias?
type ASIN = String
def update(asins: Seq[ASIN])

Is it possible to defer macro expansion until abstract type is bound to specific type

I might be using incorrect terminology, but here is example what I would like to achieve. Lets say I have the following macro:
def generateField[T]: AnyRef =
macro generateFieldImpl[T]
def generateFieldImpl[T: c.AbsTypeTag](c: Context): c.Expr[AnyRef] = {
/**
* here I'm looking at the type T by reflection to see now many members it has
* and based on that I'm generating TupleN[Array[Byte], ...](null, ...)
* where N is number of members in class represented by type T
*/
}
I'm planning to use only case classes as T.
When I use this macro with case class it works great, but now I'd like to add a level of abstraction:
trait WithGeneratedField[T] {
val _myField = generateField[T]
}
The problem I'm having is that macro gets expanded when trait is being declared and at that point T is known as an abstract type 'T'. Is there any way to defer macro expansion until I mix-in this trait with something concrete? For instance:
case class MyClass(a: String, b: Int) extends WithGeneratedField[MyClass]
At the end my goal is to use macro to add a generated field to a case class. Maybe there is a better way of doing that?
I would be surprised if this turns possible in 2.10.0.
With macro types or macro annotations (http://scalamacros.org/future.html) it should be pretty straightforward. We're going to work on these new flavors of macros as soon as we release 2.10.0-final, but it's hard to predict the ETA. Maybe winter of 2012 - spring of 2013.