Creating Instance of trait - scala

Given the following:
scala> trait Bip[T]
defined trait Bip
scala> trait Bop[R <: Bip[R]]
defined trait Bop
My understanding is that R's upper limit is the type Bip[R]. If so, it's not clear to me what type can satisfy this constraint.
For example, if I want to create a Bop[Int], then doesn't the following least upper bound resolve to Any?
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> lub(List(typeOf[Int], typeOf[Bip[Int]]))
res22: reflect.runtime.universe.Type = Any

This looks like an example of F-bounded polymorphism (there's a brief explanation here). You cannot create things like Bop[Int] but it's easy to create a new recursively-defined type that satisfies the constraint:
scala> case class Foo(bar: String) extends Bip[Foo]
defined class Foo
scala> trait Baz extends Bop[Foo]
defined trait Baz
So the only types that can satisfy R are those that are defined to extend Bip parameterized to themselves.

Related

Scala types: reflect: How to find least upper bound of two types at runtime

I'm implementing some expressions using Scala type system. To determine the type of if-then-else expression I need to be able to implement the following function
def leastUpperBound(thenPartType: Type, elsePartType: Type): Type
Is there a function somewhere in scala.reflect._ to perform the evaluation? Or do I have to implement the search with those *TypeApi extractors?
Thanks in advance
Yes, the universe has a method lub just for that:
import reflect.runtime.universe._
def leastUpperBound(thenPartType: Type, elsePartType: Type): Type =
lub(List(thenPartType, elsePartType))
Using it:
trait Base
class A extends Base
class B extends Base
scala> com.Main.leastUpperBound(typeOf[A], typeOf[B])
res0: reflect.runtime.universe.Type = Base
scala> com.Main.leastUpperBound(typeOf[A], typeOf[String])
res1: reflect.runtime.universe.Type = java.lang.Object
scala> com.Main.leastUpperBound(typeOf[A], typeOf[Int])
res1: reflect.runtime.universe.Type = Any

How to iterate all the product types in a coproduct using shapeless?

Let's say I have a coproduct (a sealed trait) such as
sealed trait Traity
case object Foo extends Traity
case class Bar() extends Traity
case class Baz() extends Traity
Using shapeless, I can apply polymorphic functions to specific instances but what I'd like to do is to apply a zero-parameter (no-instance) polymorphic function to all the products (i.e. case classes and case objects). I have no idea what the syntax would look like, but something conceptually like:
object mypoly extends Poly1 {
implicit def traity[T <: Traity] = when[T]( getClass[T].toString )
}
iterate[Traity](mypoly) // gives List("Foo", "Bar", "Baz")
would suit my purposes.
For the example use case in your question, this is actually very straightforward:
import shapeless._
class NameHelper[A] {
def apply[C <: Coproduct, K <: HList]()(implicit
gen: LabelledGeneric.Aux[A, C],
keys: ops.union.Keys.Aux[C, K],
toSet: ops.hlist.ToTraversable.Aux[K, Set, Symbol]
): Set[String] = toSet(keys()).map(_.name)
}
def names[A] = new NameHelper[A]
And then:
scala> names[Traity]()
res0: Set[String] = Set(Bar, Baz, Foo)
(I'm using a Set since the order you're getting is just alphabetical—it's not currently possible to enumerate the constructors in declaration order, although I'd personally prefer that.)
If you'd like a more generic answer, an adaptation of the code in the question I linked above shouldn't be too bad—I'd be happy to add it here later.

Scala: Placing type at bottom of inheritance tree

Scala defines a type called Nothing that is a sub-type of all types. Is it possible to define our own "bottom types" that should be at the bottom of an inheritance tree that extends from a given super-type?
For example, suppose I have some type Foo, and I want to say Xyzzy should be at the bottom of Foo's inheritance tree - in other words, it should inherit from anything that inherits from Foo. If we introduce a new type Bar, and Bar <: Foo, then Xyzzy <: Bar. I'm basically looking for a way to say class Xyzzy isBottom Foo { ... }. Is there any way to achieve this directly, or indirectly achieve this effect?
It is possible to come close to the idea you're looking to do. This is not a general "bottom" type for all types in an inheritance chain. Instead, it's a bottom type specific to traits that use generics. You need to reuse Nothing in the type definition within the inheritance structure. Take a look at List[_] to see how they've defined Nil:
case class ::[A](value: A, next: List[A]) extends List[A]
case object Nil extends List[Nothing]
Hence, Nil is a List[A] for all A because the type parameter of list is defined as List[+A].
This doesn't work:
class Foo
abstract final class Xyzzy extends Foo
class Bar extends Foo
 
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
scala> typeOf[Xyzzy] <:< typeOf[Foo]
res0: Boolean = true
scala> typeOf[Xyzzy] <:< typeOf[Bar]
res1: Boolean = false
It appears that Nothing is handled specially by the compiler.
I mean you could do this
trait Foo
abstract final class Xyzzy extends Foo
implicit def XyzzyIsBottom[A <: Foo]: Xyzzy <:< A = null
// Example usage
class X extends Foo
def xyzzyToX(x: Xyzzy): X = x

Default type parameters in scala

i have this trait
trait Extractor extends Mapping[Node]
what's the simplest way to change it to take a type parameter with a default value
trait Extractor[T] extends Mapping[**T if given else Node**]
other similar questions involves some irrelevant details about upper and lower type bounds
I think you want to overload Extractor to be of kind * and of kind * -> *. Overloading is usually best avoided, so instead I'd recommend,
scala> trait Mapping[T]
defined trait Mapping
scala> trait Node
defined trait Node
scala> trait Extractor[T] extends Mapping[T]
defined trait Extractor
scala> type NodeExtractor = Extractor[Node]
defined type alias NodeExtractor
scala> val ne = new NodeExtractor {}
ne: NodeExtractor = $anon$1#1ebdcc9a
If Extractor[Node] is the common case, then you could optimize for that and do something like this,
scala> trait ExtractorT[T] extends Mapping[T]
defined trait ExtractorT
scala> type Extractor = ExtractorT[Node]
defined type alias Extractor
scala> val ne = new Extractor {}
ne: Extractor = $anon$1#3d70fe39

Why are traits instantiable?

As far as I've learned, traits in Scala are similar to interfaces in Java except methods are allowed to have an implementation. Also, in contrast to Scala classes, you can't pass them arguments for construction.
So far, so good. But why am I allowed to instantiate them? Really, I don't see a good reason to allow this.
You don't really instantiate them. As you drew a parallel with Java, let's go further into it. You are able in Java to build a Anonymous class out of an abstract class or of an Interface. It is almost the same in Scala:
scala> trait A
defined trait A
scala> new A {}
res0: A = $anon$1#5736ab79
Note that the curly braces are mandatory when you create an object from a trait. For example, yon cannot do:
scala> new A
<console>:9: error: trait A is abstract; cannot be instantiated
new A
^
While it would works perfectly for a class:
scala> class B
defined class B
scala> new B
res2: B = B#213526b0
Of course if some elements in your trait are not implemented, you need to implement them when you create the object:
scala> trait C {def foo: Int}
defined trait C
scala> new C {}
<console>:9: error: object creation impossible, since method foo in trait C of type => Int is not defined
new C {}
^
scala> new C {def foo = 42}
res4: C = $anon$1#744957c7