Context bound in Scala - scala

I am learning Context bound in Scala.
In the below code, I am invoking multiplication operator on the integer parameter. But it errors out. 'a' is considered as type parameter; but it is actually not as per my understanding. Can someone please help.
scala> class Sample[T]
defined class Sample
scala> def method[Int:Sample](a:Int) = a * a
<console>:12: error: value * is not a member of type parameter Int
def method[Int:Sample](a:Int) = a * a
Thanks!

Context bounds are syntactic sugar for implicit generic parameters that are parameterized by some type you're using. This concept is also known as "type class". You define some generic trait, such as your Sample[T], and then you provide implicit(!) instances of that trait for various concrete values of T. We call them "type class instances".
Why implicit? It's an implementation detail that Scala uses to achieve the type class mechanism; type classes also exist in e.g. Haskell, but the mechanism itself is a bit different. Anyways, you can then define a method such as your def method which requires a type class instance for some type. And you can do this with context bound syntax, or with a more verbose and more explicit standard syntax for implicit parameters.
Your definition is using the context bound. But there is something wrong with your example, as indicated by the compilation error. Let's first see a proper example that uses the type class concept correctly.
// type class definition:
trait Sample[T] {
def getSample: T
}
// type class instance(s):
object Sample {
implicit val sampleInt: Sample[Int] =
new Sample[Int] { def getSample = 42 }
}
And now the usage:
import Sample._
// using the context bound syntax
def method1[T : Sample](t: T) = t.getSample
// not using the context bound syntax
def method2(t: T)(implicit ev: Sample[T]) = t.getSample
What we're doing is saying - there is some value t of type T, we don't know much about it, but what we do know is that there is a Sample type class instance available for it. This allows us to do t.getSample.
And now, to finally provide the answer to your problem:
In your code, you are mixing things up. Your T is actually called Int. You intended to use the Int type, but what you did instead is that you named your generic parameter Int. I could have answered this with way less text, but I figured perhaps you would find the bigger picture interesting, rather than just pointing out the mistake.

The type parameter named Int does not represent concrete integer type scala.Int. Instead it is just a confusing coincidence that the type parameter was given the same name Int as the concrete type. If you give it some other name such as T
def method[T: Sample](a: T): T = a * a
the error message should make more sense. Now we see * is not defined for T since Sample type class does not yet provide such capability. Here is an example of how correct syntactic usage might look usage
trait Sample[T] {
def mult(a: T, b: T): T
}
def method[T: Sample](a: T): T = implicitly[Sample[T]].mult(a, a)
def method[T](a: T)(implicit ev: Sample[T]): T = ev.mult(a, a)
You could also have a look at Numeric type class which provides such functionality out of the box
def method[T](a: T)(implicit num: Numeric[T]): T = num.times(a, a)

Your method has a type parameter called Int which shadows the actual Int, just like defining a normal variable would shadow something from an outer scope. The same would happen if you remove the context bound.
What you are probably trying to do is something closer to the following:
trait Sample[A] {
def someOperation(a1: A, a2: A): A
}
implicit object IntSample extends Sample[Int] {
override def someOperation(a1: Int, a2: Int): Int = a1 * a2
}
def method[T: Sample](t: T) = implicitly[Sample[T]].someOperation(t, t)
method(4) // compiles and returns 16
//method("4") // doesn't compile, no implicit instance of Sample[String] in scope
You can play around with this code here on Scastie.

Related

Implicit conversion where there resulting type is a type projection on a generic type

I have some scala 2.13 code that basically boils down to this
import scala.language.implicitConversions
trait Base {
type V
def v: V
}
case class Derived(v: Int) extends Base {
type V = Int
}
object TestImplicitConversion {
implicit def getV[T <: Base](a: T): T#V = a.v
val a: Int = Derived(5)
}
Here I would expect the compiler to use the implicit conversion getV to convert Derived to Int, but the code does not compile. Manually adding the call to getV, will make the code compile. Can someone help me understand why the conversion where in the standard it is explained.
The way I found of making such a conversion work is by adding a second generic parameter and a constraint
implicit def getV2[T <: Base, S](a: T)(implicit constraint: T#V =:= S): S = constraint(a.v)
with this version the compiler uses the conversion and the code does compile.
Edit:
The alternative solution provided by #user using refinement type does indeed seem like a better approach. But it does not really provide an answer to why it original implementation does not work. So I am still interested in understanding why the compiler does not use the implicit def when an explicit call will make the code compile.
As gianluca aguzzi mentioned in the comments, type projection is unsound and should be avoided. Moreover, T is not a concrete type, so you can't use projections on it anyway. You can accept only Base#V as a type parameter instead, and use a refinement type for the type of a:
implicit def get[T](a: Base { type V = T }): T = a.v
Thus, you can avoid casting and type projections.
Scastie

How can I write a function have a polymorphic return type based on the type argument of its type parameter?

I have some code like this:
sealed trait Foo[A] {
def value: A
}
case class StringFoo(value: String) extends Foo[String]
case class IntFoo(value: Int) extends Foo[Int]
I'd like to have a function which can use the A type given a subtype's type parameter.
// Hypothetical invocation
val i: Int = dostuff[IntFoo](param)
val s: String = dostuff[StringFoo](param)
I can't figure out how to declare dostuff in a way that works. The closest thing I can figure out is
def dostuff[B <: Foo[A]](p: Param): A
But that doesn't work because A is undefined in that position. I can do something like
def dostuff[A, B <: Foo[A]](p: Param): A
But then I have to invoke it like dostuff[String, StringFoo](param) which is pretty ugly.
It seems like the compiler should have all the information it needs to move A across to the return type, how can I make this work, either in standard scala or with a library. I'm on scala 2.10 currently if that impacts the answer. I'm open to a 2.11-only solution if it's possible there but impossible in 2.10
Another option is to use type members:
sealed trait Foo {
type Value
def value: Value
}
case class StringFoo(value: String) extends Foo { type Value = String }
case class IntFoo(value: Int) extends Foo { type Value = Int }
def dostuff[B <: Foo](p: Any): B#Value = ???
// Hypothetical invocation
val i: Int = dostuff[IntFoo](param)
val s: String = dostuff[StringFoo](param)
Note that both solutions mainly work around the syntactic restriction in Scala, that you cannot fix one type parameter of a list and have the compiler infer the other.
As you might know, if you have a parameter of type Foo[A], then you can make the method generic in just A:
def dostuff[A](p: Foo[A]): A = ???
Since that might not always be the case, we can try to use an implicit parameter that can express the relationship between A and B. Since we can't only apply some of the generic parameters to a method call (generic parameter inference is all or nothing), we have to split this into 2 calls. This is an option:
case class Stuff[B <: Foo[_]]() {
def get[A](p: Param)(implicit ev: B => Foo[A]): A = ???
}
You can check the types in the REPL:
:t Stuff[IntFoo].get(new Param) //Int
:t Stuff[StringFoo].get(new Param) //String
Another option along the same lines, but using an anonymous class, is:
def stuff[B <: Foo[_]] = new {
def apply[A](p: Param)(implicit ev: B <:< Foo[A]): A = ???
}
:t stuff[IntFoo](new Param) //Int
Here, I've used apply in stead of get, so you can apply the method more naturally. Also, as suggested in your comment, here I've used <:< in the evidence type. For those looking to learn more about this type of generalized type constraint, you can read more here.
You might also consider using abstract type members instead of generic parameters here. When struggling with generic type inference, this often provides an elegant solution. You can read more about abstract type members and their relationship to generics here.

how to write parametric-typed function where the parameter class declares some method(s) in scala?

I deal with Scala problem which I can't properly name, so maybe there is already answer somewhere here (please be patient).
Assuming this code:
class A {def foo() = 5}
class B {def foo() = 6}
def fooer[T](x:T) = x.foo()
I get error:
<console>:7: error: value foo is not a member of type parameter T
def fooer[T](x:T) = x.foo
This perfectly makes sense as compiler can't possibly know what type T will be passed. So finally the question - how can I implement typed function so it accepts only types with foo method declared?
Please note that I don't seek enum alternitives (see doc) as I don't know how many classes are there (external library). Also the classes have no common predecessor class or trait and they can't be modified.
Is this even possible? C++ language support this behavior using templates. I prefer solution which doesn't use reflection API.
Thanks :)
I tried some more definitions of fooer such as
def fooer[T <: {def foo(): Integer}](x:T) = x.foo()
fooer[A](new A)
<console>:10: error: type arguments [A] do not conform to method fooer's type parameter bounds [T <: AnyRef{def foo(): Integer}]
fooer[A](new A)
^
but with no success
The problem is that A.foo returns an Int not an Integer. If you change your method to:
def fooer[T <: {def foo(): Int}](x:T) = x.foo()
then it will work.

What is `class A[_]` useful for?

The types of symbols class A[_] or of def a[_](x: Any) have a type parameter that can't be referenced in the body, thus I don't see where it is useful for and why it compiles. If one tries to reference this type parameter, an error is thrown:
scala> class A[_] { type X = _ }
<console>:1: error: unbound wildcard type
class A[_] { type X = _ }
^
scala> def a[_](x: Any) { type X = _ }
<console>:1: error: unbound wildcard type
def a[_](x: Any) { type X = _ }
^
Can someone tell me if such a type has a use case in Scala? To be exact, I do not mean existential types or higher kinded types in type parameters, only those litte [_] which form the complete type parameter list.
Because I did not get the answers I expected, I brought this to scala-language.
I paste here the answer from Lars Hupel (so, all credits apply to him), which mostly explains what I wanted to know:
I'm going to give it a stab here. I think the use of the feature gets
clear when talking about type members.
Assume that you have to implement the following trait:
trait Function {
type Out[In]
def apply[In](x: In): Out[In]
}
This would be a (generic) function where the return type depends on
the input type. One example for an instance:
val someify = new Function {
type Out[In] = Option[In] def
apply[In](x: In) = Some(x)
}
someify(3) res0: Some[Int] = Some(3)
So far, so good. Now, how would you define a constant function?
val const0 = new Function {
type Out[In] = Int
def apply[In](x: In) = 0
}
const0(3) res1: const0.Out[Int] = 0
(The type const0.Out[Int] is equivalent to Int, but it isn't
printed that way.)
Note how the type parameter In isn't actually used. So, here's how
you could write it with _:
val const0 = new Function {
type Out[_] = Int
def apply[In](x: In) = 0
}
Think of _ in that case as a name for the type parameter which
cannot actually be referred to. It's a for a function on the type
level which doesn't care about the parameter, just like on value
level:
(_: Int) => 3 res4: Int => Int = <function1>
Except …
type Foo[_, _] = Int
<console>:7: error: _ is already defined as type _
type Foo[_, _] = Int
Compare that with:
(_: Int, _: String) => 3 res6: (Int, String) => Int = <function2>
So, in conclusion:
type F[_] = ConstType // when you have to implement a type member def
foo[_](...) // when you have to implement a generic method but don't
// actually refer to the type parameter (occurs very rarely)
The main thing you mentioned, class A[_], is completely symmetric to
that, except that there's no real use case.
Consider this:
trait FlyingDog[F[_]] { def swoosh[A, B](f: A => B, a: F[A]): F[B] }
Now assume you want to make an instance of FlyingDog for your plain
old class A.
new FlyingDog[A] { ... }
// error: A takes no type parameters, expected: one
// (aka 'kind mismatch')
There are two solutions:
Declare class A[_] instead. (Don't do that.)
Use a type lambda:
new FlyingDog[({ type λ[α] = A })#λ]
or even
new FlyingDog[({ type λ[_] = A })#λ]
I had some casual ideas about what it could mean here:
https://issues.scala-lang.org/browse/SI-5606
Besides the trivial use case, asking the compiler to make up a name because I really don't care (though maybe I'll name it later when I implement the class), this one still strikes me as useful:
Another use case is where a type param is deprecated because
improvements in type inference make it superfluous.
trait T[#deprecated("I'm free","2.11") _, B <: S[_]]
Then, hypothetically,
one could warn on usage of T[X, Y] but not T[_, Y].
Though it's not obvious whether the annotation would come before (value parameter-style) or after (annotation on type style).
[Edit: "why it compiles": case class Foo[_](i: Int) still crashes nicely on 2.9.2]
The underscore in Scala indicates an existential type, i.e. an unknown type parameter, which has two main usage:
It is used for methods which do not care about the type parameter
It is used for methods where you want to express that one type parameter is a type constructor.
A type constructor is basically something that needs a type parameter to construct a concrete type. For example you can take the following signature.
def strangeStuff[CC[_], B, A](b:B, f: B=>A): CC[A]
This is a function that for some CC[_] , for example a List[_], creates a List[A] starting from a B and a function B=>A.
Why would that be useful? Well it turns out that if you use that mechanism together with implicits and typeclasses, you can get what is called ad-hoc polymorphism thanks to the compiler reasoning.
Imagine for example you have some higher-kinded type: Container[_] with a hierarchy of concrete implementations: BeautifulContainer[_], BigContainer[_], SmallContainer[_]. To build a container you need a
trait ContainerBuilder[A[_]<:Container[_],B] {
def build(b:B):A[B]
}
So basically a ContainerBuilder is something that for a specific type of container A[_] can build an A[B] using a B.
While would that be useful ? Well you can imagine that you might have a function defined somewhere else like the following:
def myMethod(b:B)(implicit containerBuilder:ContainerBuilder[A[_],B]):A[B] = containerBuilder.build(b)
And then in your code you might do:
val b = new B()
val bigContainer:BigContainer[B] = myMethod(b)
val beautifulContainer:BeautifulContainer[B] = myMethod(b)
In fact, the compiler will use the required return type of myMethod to look for an implicit which satisfies the required type constraints and will throw a compile error if there is no ContainerBuilder which meets the required constraints available implicitely.
That's useful when you deal with instances of parametrized types without caring of the type parameter.
trait Something[A] {
def stringify: String
}
class Foo extends Something[Bar] {
def stringify = "hop"
}
object App {
def useSomething(thing: Something[_]) :String = {
thing.stringify
}
}

Passing scala.math.Integral as implicit parameter

I have read the answer to my question about scala.math.Integral but I do not understand what happens when Integral[T] is passed as an implicit parameter. (I think I understand the implicit parameters concept in general).
Let's consider this function
import scala.math._
def foo[T](t: T)(implicit integral: Integral[T]) { println(integral) }
Now I call foo in REPL:
scala> foo(0)
scala.math.Numeric$IntIsIntegral$#581ea2
scala> foo(0L)
scala.math.Numeric$LongIsIntegral$#17fe89
How does the integral argument become scala.math.Numeric$IntIsIntegral and scala.math.Numeric$LongIsIntegral ?
The short answer is that Scala finds IntIsIntegral and LongIsIntegral inside the object Numeric, which is the companion object of the class Numeric, which is a super class of Integral.
Read on for the long answer.
Types of Implicits
Implicits in Scala refers to either a value that can be passed "automatically", so to speak, or a conversion from one type to another that is made automatically.
Implicit Conversion
Speaking very briefly about the latter type, if one calls a method m on an object o of a class C, and that class does not support method m, then Scala will look for an implicit conversion from C to something that does support m. A simple example would be the method map on String:
"abc".map(_.toInt)
String does not support the method map, but StringOps does, and there's an implicit conversion from String to StringOps available (see implicit def augmentString on Predef).
Implicit Parameters
The other kind of implicit is the implicit parameter. These are passed to method calls like any other parameter, but the compiler tries to fill them in automatically. If it can't, it will complain. One can pass these parameters explicitly, which is how one uses breakOut, for example (see question about breakOut, on a day you are feeling up for a challenge).
In this case, one has to declare the need for an implicit, such as the foo method declaration:
def foo[T](t: T)(implicit integral: Integral[T]) {println(integral)}
View Bounds
There's one situation where an implicit is both an implicit conversion and an implicit parameter. For example:
def getIndex[T, CC](seq: CC, value: T)(implicit conv: CC => Seq[T]) = seq.indexOf(value)
getIndex("abc", 'a')
The method getIndex can receive any object, as long as there is an implicit conversion available from its class to Seq[T]. Because of that, I can pass a String to getIndex, and it will work.
Behind the scenes, the compile changes seq.IndexOf(value) to conv(seq).indexOf(value).
This is so useful that there is a syntactic sugar to write them. Using this syntactic sugar, getIndex can be defined like this:
def getIndex[T, CC <% Seq[T]](seq: CC, value: T) = seq.indexOf(value)
This syntactic sugar is described as a view bound, akin to an upper bound (CC <: Seq[Int]) or a lower bound (T >: Null).
Please be aware that view bounds are deprecated from 2.11, you should avoid them.
Context Bounds
Another common pattern in implicit parameters is the type class pattern. This pattern enables the provision of common interfaces to classes which did not declare them. It can both serve as a bridge pattern -- gaining separation of concerns -- and as an adapter pattern.
The Integral class you mentioned is a classic example of type class pattern. Another example on Scala's standard library is Ordering. There's a library that makes heavy use of this pattern, called Scalaz.
This is an example of its use:
def sum[T](list: List[T])(implicit integral: Integral[T]): T = {
import integral._ // get the implicits in question into scope
list.foldLeft(integral.zero)(_ + _)
}
There is also a syntactic sugar for it, called a context bound, which is made less useful by the need to refer to the implicit. A straight conversion of that method looks like this:
def sum[T : Integral](list: List[T]): T = {
val integral = implicitly[Integral[T]]
import integral._ // get the implicits in question into scope
list.foldLeft(integral.zero)(_ + _)
}
Context bounds are more useful when you just need to pass them to other methods that use them. For example, the method sorted on Seq needs an implicit Ordering. To create a method reverseSort, one could write:
def reverseSort[T : Ordering](seq: Seq[T]) = seq.reverse.sorted
Because Ordering[T] was implicitly passed to reverseSort, it can then pass it implicitly to sorted.
Where do Implicits Come From?
When the compiler sees the need for an implicit, either because you are calling a method which does not exist on the object's class, or because you are calling a method that requires an implicit parameter, it will search for an implicit that will fit the need.
This search obey certain rules that define which implicits are visible and which are not. The following table showing where the compiler will search for implicits was taken from an excellent presentation about implicits by Josh Suereth, which I heartily recommend to anyone wanting to improve their Scala knowledge.
First look in current scope
Implicits defined in current scope
Explicit imports
wildcard imports
Same scope in other files
Now look at associated types in
Companion objects of a type
Companion objects of type parameters types
Outer objects for nested types
Other dimensions
Let's give examples for them.
Implicits Defined in Current Scope
implicit val n: Int = 5
def add(x: Int)(implicit y: Int) = x + y
add(5) // takes n from the current scope
Explicit Imports
import scala.collection.JavaConversions.mapAsScalaMap
def env = System.getenv() // Java map
val term = env("TERM") // implicit conversion from Java Map to Scala Map
Wildcard Imports
def sum[T : Integral](list: List[T]): T = {
val integral = implicitly[Integral[T]]
import integral._ // get the implicits in question into scope
list.foldLeft(integral.zero)(_ + _)
}
Same Scope in Other Files
This is like the first example, but assuming the implicit definition is in a different file than its usage. See also how package objects might be used in to bring in implicits.
Companion Objects of a Type
There are two object companions of note here. First, the object companion of the "source" type is looked into. For instance, inside the object Option there is an implicit conversion to Iterable, so one can call Iterable methods on Option, or pass Option to something expecting an Iterable. For example:
for {
x <- List(1, 2, 3)
y <- Some('x')
} yield, (x, y)
That expression is translated by the compile into
List(1, 2, 3).flatMap(x => Some('x').map(y => (x, y)))
However, List.flatMap expects a TraversableOnce, which Option is not. The compiler then looks inside Option's object companion and finds the conversion to Iterable, which is a TraversableOnce, making this expression correct.
Second, the companion object of the expected type:
List(1, 2, 3).sorted
The method sorted takes an implicit Ordering. In this case, it looks inside the object Ordering, companion to the class Ordering, and finds an implicit Ordering[Int] there.
Note that companion objects of super classes are also looked into. For example:
class A(val n: Int)
object A {
implicit def str(a: A) = "A: %d" format a.n
}
class B(val x: Int, y: Int) extends A(y)
val b = new B(5, 2)
val s: String = b // s == "A: 2"
This is how Scala found the implicit Numeric[Int] and Numeric[Long] in your question, by the way, as they are found inside Numeric, not Integral.
Companion Objects of Type Parameters Types
This is required to make the type class pattern really work. Consider Ordering, for instance... it comes with some implicits in its companion object, but you can't add stuff to it. So how can you make an Ordering for your own class that is automatically found?
Let's start with the implementation:
class A(val n: Int)
object A {
implicit val ord = new Ordering[A] {
def compare(x: A, y: A) = implicitly[Ordering[Int]].compare(x.n, y.n)
}
}
So, consider what happens when you call
List(new A(5), new A(2)).sorted
As we saw, the method sorted expects an Ordering[A] (actually, it expects an Ordering[B], where B >: A). There isn't any such thing inside Ordering, and there is no "source" type on which to look. Obviously, it is finding it inside A, which is a type parameter of Ordering.
This is also how various collection methods expecting CanBuildFrom work: the implicits are found inside companion objects to the type parameters of CanBuildFrom.
Outer Objects for Nested Types
I haven't actually seen examples of this. I'd be grateful if someone could share one. The principle is simple:
class A(val n: Int) {
class B(val m: Int) { require(m < n) }
}
object A {
implicit def bToString(b: A#B) = "B: %d" format b.m
}
val a = new A(5)
val b = new a.B(3)
val s: String = b // s == "B: 3"
Other Dimensions
I'm pretty sure this was a joke. I hope. :-)
EDIT
Related questions of interest:
Context and view bounds
Chaining implicits
The parameter is implicit, which means that the Scala compiler will look if it can find an implicit object somewhere that it can automatically fill in for the parameter.
When you pass in an Int, it's going to look for an implicit object that is an Integral[Int] and it finds it in scala.math.Numeric. You can look at the source code of scala.math.Numeric, where you will find this:
object Numeric {
// ...
trait IntIsIntegral extends Integral[Int] {
// ...
}
// This is the implicit object that the compiler finds
implicit object IntIsIntegral extends IntIsIntegral with Ordering.IntOrdering
}
Likewise, there is a different implicit object for Long that works the same way.