Default type parameters in scala - 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

Related

Scala type constraint precedence in implicit resolution

I have these 2 implicits
trait A[T] {
val name: String
}
trait B
object A {
implicit def product[T <: Product] = new A[T] {
override val name: String = "product"
}
implicit def childOfB[T <: Product with B] = new A[T] {
override val name: String = "child of B"
}
}
and if I try to find an implicit instance of A[C] where C is
case class C() extends B
childOfB will be selected.
I know it is logical but why does this happen? I cannot find it documented anywhere.
Scala Language Specification says:
If there are several eligible arguments which match the implicit
parameter's type, a most specific one will be chosen using the rules
of static overloading resolution.
Overloading resolution has a notion of one symbol being more specific than other. Precise, general definition of specificity is quite complex (as you can see in the specification linked above) but in your case it boils down to the fact that childOfB covers strictly a subset of types covered by product and therefore is more specific.
Specification says
If there are several eligible arguments which match the implicit
parameter's type, a most specific one will be chosen using the rules
of static overloading resolution.
To extend #ghik's answer, from Programmming in Scala,
To be more precise, one implicit conversion is more specific than another if one of the following applies:
The argument of the former is a subtype of the latter's
Both conversions are methods, and the enclosing class of the former extends the enclosing class of the latter
My guess is that "argument" in that quote refers also to type parameters, as is sugggested by
object A {
implicit def A2Z[T <: A] = new Z[T] {println("A")}
implicit def B2Z[T <: B] = new Z[T] {println("B")}
}
trait A
trait B extends A
trait Z[T]
def aMethod[T <: A](implicit o: Z[T]) = ()
implicit val a: A = new A {}
aMethod // prints B even though we started with an A

Relationship between parameterized class with different type, Scala

In Scala,
What is the relationship between parameterized class with different type?
For example,
class A[T]
What is the relationship between A[Int] (or A[String]) and A?
and what is the relationship between A[Int] and A[String] ?
I want to know, because I would like to do something like
case class A[T](v: T) { def print = println(v) }
def iter(s: Seq[A[???]]) = s.map(print) // What is the proper annotation of '???'
iter(Seq(A(1), A("Hello")) // 1 Hello
What is the relationship between A[Int] and A?
A is a type constructor of kind * → *, and A[Int] is one of the possible results of apply a type (Int) to the type constructor A.
What is the relationship between A[Int] and A[String]?
The least upper bound between these two types is A[_ >: String with Int], which can only be instantiated to A[Any] since it's the only super class of String and Int.
What is the proper annotation of '???'
In your example that would be Any, or a type parameter you could add to your def iter that would itself be instantiated to Any.
Types are related using Variance.
To answer your question, Java's wildcards equivalent in Scala is Existential types. So you can specify something like this:
def iter(s: Seq[A[_]]) = s.map(_.print)
which is equivalent to:
def iter(s: Seq[A[T] forSome {type T}]) = s.map(_.print)
You can also specify bounds like below:
def iter(s: Seq[A[_ <: CharSequence]]) = s.map(_.print)
println(iter(Seq(A[StringBuilder](new StringBuilder("Test")), A[String]("Hello"))))
[Explicit type specified in constructors to avoid implicit conversion to required type CharSequence].
Note that the following would not compile though:
def iter(s: Seq[A[CharSequence]]) = s.map(_.print)
println(iter(Seq(A[StringBuilder](new StringBuilder("Test")), A[String]("Hello"))))
This is where variance specification in class would help:
case class A[+T](v: T) {
def print = v
}
def iter(s: Seq[A[CharSequence]]) = s.map(_.print)
println(iter(Seq(A[StringBuilder](new StringBuilder("Test")), A[String]("Hello"))))

scala: Parameterize by Type Union

I needed a type Union to force restriction on types, So as per answer in here, I defined my Union as:
sealed trait Value[T]
object Value{
implicit object NumberWitness extends Value[Int]
implicit object StringWitness extends Value[String]
}
Now, How do i create a list or class parameterized by this type union? Is it possible to do so?? I tried following syntax in repl, but without any luck:
scala> import Value._
import Value._
scala> def list[V: Value] = List("hello", 1)
list: [V](implicit evidence$1: Value[V])List[Any]
scala> list
<console>:18: error: ambiguous implicit values:
both object NumberWitness in object Value of type Value.NumberWitness.type
and object StringWitness in object Value of type Value.StringWitness.type
match expected type Value[V]
list
^
Or Is it possible to do so with advanced FP libraries like scalaz or cats??
This is called type class, not type union. And they are intended to allow you to write methods which work either with Int or with String, e.g.
def listOfValues[V: Value](x: V) = List(x)
listOfValues(1) // works
listOfValues("") // works
listOfValues(0.0) // doesn't work
listOfValues(1, "") // doesn't work
not to allow mixing different types.
You can do it using existential types, e.g.
case class WithValue[V: Value](x: V)
object WithValue {
implicit def withValue[V: Value](x: V) = WithValue(x)
}
def list = List[WithValue[_]]("hello", 1)
but I would not recommend actually doing that. There is quite likely a better way to solve your problem.
In particular, consider using simply
// not sealed if you need to add other types elsewhere
// can be Value[T] instead
sealed trait Value
case class IntValue(x: Int) extends Value
case class StringValue(x: Int) extends Value
// add implicit conversions to IntValue and StringValue if desired
List(StringValue("hello"), IntValue(1))

Context bounds for generic polymorphic data in collection

I have the simplified situation:
abstract sealed trait Top
class A[T] extends Top
class B[T] extends Top
class Typeclass[T]
implicit def a[T] = new Typeclass[A[T]]
implicit def b[T] = new Typeclass[B[T]]
Now I have a Map[String, Top] and want to use an operation on all values in the map that require the presence of an instance of Typeclass to be available in the context. This will not compile as the concrete types of the values in the map are not visible from its type and I can therefore not set a context bound for them.
Is there a way to tell the compiler that in fact there will always be an instance available? In this example this is given as there are implicit functions to generate those instances for every concrete subtype of Top.
Or is the only solution to use a HList and recurse over its type requiring all the instances to be in context?
I recommend using some variation on this adaptation of Oleg's Existentials as universals in this sort of situation ... pack the the type class instance along with the value it's the instance for,
abstract sealed trait Top
class A[T] extends Top
class B[T] extends Top
class Typeclass[T]
implicit def a[T] = new Typeclass[A[T]]
implicit def b[T] = new Typeclass[B[T]]
trait Pack {
type T <: Top
val top: T
implicit val tc: Typeclass[T]
}
object Pack {
def apply[T0 <: Top](t0: T0)(implicit tc0: Typeclass[T0]): Pack =
new Pack { type T = T0 ; val top = t0 ; val tc = tc0 }
}
val m = Map("a" -> Pack(new A[Int]), "b" -> Pack(new B[Double]))
def foo[T: Typeclass](t: T): Unit = ()
def bar(m: Map[String, Pack], k: String): Unit =
m.get(k).map { pack =>
import pack._ // imports T, top and implicit tc
foo(top) // instance available for call of foo
}
bar(m, "a")
As discussed in comment it would be more convenient to have the typeclass defined on Top, and it might be done with pattern matching.
supposing part of the definition of the typeclass is
def f[T](t: T): FResult[T],
and you have the corresponding implentations
def fOnA[T](t: A[T]): FResult[A[T]] = ...
def fOnB[T](t: B[T]): FResult[B[T]] = ...
Then you can define
def fOnT(t: Top) : FResult[Top] = t match {
case a: A[_] => fOnA(a)
// provided an FResult[A[T]] is an FResult[Top],
// or some conversion is possible
case b: B[_] => fOnB(b)
}
If is both legal and safe to call a generic method, such as fOnA[T] with an existential (a matching A[_])
However, it might be difficult to convince the compiler that the parameter you pass to f or the result you get are ok, given the reduced information of the existential. If so, please post the signatures you need.

Creating Instance of trait

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.