Scala: def method[A](some params) vs def method(some params) - scala

I'm having trouble finding what this is called and what the difference is exactly between defining a method like this:
def method[A](//...//) {}
or
def method(//...//) {}
Also, is def method[A] the same as def method[Any]?
Help would be greatly appreciated.

def method[A] defines a generic type A. Used like this, with no refinement, it is a wildcard that can be satisfied by any type. (You can specify that only some subtypes are allowed with syntax like [A <: Foo], where Foo is a class or trait you've defined.)
Why would you want to do this? Most likely, you want a method that returns the same type that it takes as an argument (or some variation thereof--maybe it takes a list of that type and returns an array of that type):
def method[A](a: A): A = ...
Since you don't know anything about A, it is as generic as Any.
Now, there's nothing special about A. You could put anything there, even Any:
def method[Any](a: Any) ... // Don't do this!
But this would be supremely confusing, because this isn't your standard Any type that is at the top of the inheritance hierarchy--it's a generic type just like A, but with a longer name.
If you don't need to use a generic type, omit the [A]. For example:
def printed[A](a: A): A = { println(a); a } // Generic necessary
def printMe(a: Any) { println(a) } // Not necessary, returns Unit

Related

Context bound in 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.

Howto create a generic type class function using functors

Having this type class for converting a Map into a case class:
/**
* Type class for transforming a map of values into a case class instance.
*
* #tparam T Wanted case class type.
*/
#implicitNotFound("Missing ToCaseClassMapper implementation for type ${T}")
trait ToCaseClassMapper[T <: Product] {
def toCaseClass(map: Map[String, Any]): T
}
And this function to implicitly get the correct mapper
def toCaseClass[T <: Product](map: Map[String, Any])(implicit mapper: ToCaseClassMapper[T]): T = {
mapper.toCaseClass(map)
}
It can be used as toCaseClass[User](aUserMap) // returns User
But I also would like to be able to use this function with an Option[Map[]] or Future[Map[]] or List[Map[]].
So I implemented a generic function using a functor like this:
def toCaseClass[T <: Product, F[_]: cats.Functor](fOfMaps: F[Map[String, Any]])(implicit mapper: ToCaseClassMapper[T]): F[T] = {
cats.Functor[F].map(fOfMaps)(map => toCaseClass(map)(mapper))
}
But now this function has to be used as toCaseClass[User,List](listOfUserMaps) // returns List[User].
However, I'd would like to be able to use the function as
toCaseClass[User](listOfMaps)
toCaseClass[User](futureOfMap)
toCaseClass[User](optionOfMap)
without the need to specify the functor type.
Is this somehow possible?
Could Shapeless's Lazy be used to solve this?
Edit: solution
Thanks to #Jasper-m and #dk14 for their answers.
So the 'trick' to solve this is to capture the type 'T' first in a class before the Functor type. I liked #Jasper-m solution with the 'apply' method since that would keep the syntax almost similar to what it was before.
I made a few adjustments though. Since there was already the 'ToCaseClassMapper' class which also captures the type 'T', I decided to combine it with the 'ToCaseClass' class. Also, with #Jasper-m's approach, when using the 'toCaseClass' function when mapping over some value like Option(value).map(toCaseClass) the usage of toCaseClass had to be different for when the value was a Map or a List[Map].
My solution is now as follows:
#implicitNotFound("Missing ToCaseClassMapper implementation for type ${T}")
trait ToCaseClassMapper[T <: Product] {
def toCaseClass(map: Map[String, Any]): T
import scala.language.higherKinds
def toCaseClass[F[_]: cats.Functor, A](fOfMaps: F[Map[String, A]]): F[T] = {
cats.Functor[F].map(fOfMaps)(toCaseClass)
}
}
Since the ToCaseClassMapper instance was already implicitly available where the toCaseClass function was used, I decided to throw away that function and just replace it with mapper.toCaseClass(_). This cleaned up some unneeded code and now the syntax for using the mapper is the same regardless whether the value is a Map or Option, List, Future (or any other Functor).
Currently it's not possible in Scala to have one type parameter provided explicitly and another one in the same type parameter list be inferred, nor is it currently possible to have multiple type parameter lists for a method. A workaround is to create a helper class and split your method call in two stages: first create an instance of the helper class, then call the apply method on that object.
class ToCaseClass[T <: Product] {
def apply[F[_]: cats.Functor, A](fOfMaps: F[Map[String, A]])(implicit mapper: ToCaseClassMapper[T]): F[T] = {
cats.Functor[F].map(fOfMaps)(map => toCaseClass(map)(mapper))
}
}
def toCaseClass[T <: Product] = new ToCaseClass[T]
def toCaseClass[T <: Product](map: Map[String, Any])(implicit mapper: ToCaseClassMapper[T]): T = {
mapper.toCaseClass(map)
}
toCaseClass[User](listOfMaps)
toCaseClass[User](futureOfMap)
toCaseClass[User](optionOfMap)
Edit: As pointed out by dk14, there is still a type inference problem here, where F is inferred as Any. I don't know what causes it, but I think it is a separate orthogonal problem from the one being solved by this pattern.
Edit 2: I figured it out. It's because F is invariant in its type parameter. F[Map[String, String]] is not a subtype of F[Map[String, Any]], so the compiler does something strange and infers F as Any. A solution is to put a type parameter A instead of Any, or use an existential type Map[String,_].
This works:
class Mapper[T <: Product](implicit val mapper: ToCaseClassMapper[T]){
def toCaseClass[F[_]: cats.Functor, Z <: Map[String, Any]](fOfMaps: F[Z]): F[T] = {
cats.Functor[F].map(fOfMaps)(map => mapper.toCaseClass(map))
}
}
object Mapper{
def apply[T <: Product: ToCaseClassMapper] = new Mapper[T]{}
}
import cats.implicits._
Mapper[User].toCaseClass(List(Map("aaa" -> 0)))
Few tricks besides obvious introducing class (to split type parameters) were used as well:
1) move mapper to constructor so it could be resolved first (not sure it helped)
2) what definitely helped is to introduce Z <: Map[String, Any], otherwise scala (at least my old version 2.11.8) would infer F[_] as Any for some reason
P.S. You can use apply instead of toCaseClass as well - it would shorten the syntax

Can I override a type parmeterized method with concrete type in scala?

I want to override a type-parameterized method by assigning a concrete type to the type-parameter, something like the code below.
trait A {
def amethod[T](x: T): T
}
trait B extends A {
def amethod(x: String): String = x ++ x
}
However the compiler gives amethod overrides nothing. I cannot put [String] after amethod in trait B, as syntactically it means a type parameter named String not the type java.lang.String. I am wondering whether and how I can do something like that.
Thanks a lot.
amethod, as it's defined in trait A, is a generic method, meaning that each call can be applied to generic arguments.
What you are trying to say in trait B is to change the scope at which generality is expressed, moving it from the call site to the class definition itself. It's not possible to do it.
As it's been suggested in a comment, if you want to express generality in a class definition, the type parameter should be applied to the class, not to the method:
trait A[T] {
def amethod(x: T): T
}
trait B extends A[String] {
override def amethod(x: String): String = x ++ x
}
As an explanation of the comment saying "B breaks its contract with A", consider this code:
def foo(): A = new B {} // legal because B extends A
def bar = foo().amethod[Int](0)
What should happen? If you are tempted to say that it should be rejected by looking at the body of foo, imagine it's an abstract method instead, and some class happens to implement it in this way.

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.

Simulate partial type parameter inference with implicits?

I'm making a simple dependency injection framework, for constructor injection, in Scala. The idea is that objects that are DI'd put their required services in their constructor like regular parameters, and implement a typeclass that determines which of their arguments are taken from the container and which are passed by the user on instantiation.
So, it should look something like:
trait Container {
private singletons: Map[Class, AnyRef]
def getSingleton[T: Manifest] =
singletons(implicitly[Manifest[T]].erasure).asInstanceOf[T]
... methods for adding singletons, etc ...
}
class Foo(arg: String, svc: FooService) {
...
}
trait Constructor[T] { ??? }
object FooConstructor extends Constructor[Foo] {
def construct(arg: String)(implicit container: Container) =
new Foo(arg, container.getSingleton[FooService])
}
Now basically I'd like to be able to have a method called construct, which I can call as construct[Foo]("asd") and get a new instance of Foo with "asd" passed in to the constructor, and FooService gotten from the local container and passed in to the constructor. The idea is that it should grab the instance of the Constructor type class for Foo and in a typesafe way, know the number and types of arguments it should have. Also, and this is the hard part, I don't want to have to write out the types of the arguments - just the object to be constructed.
I've tried a couple things:
trait Constructor1[T, A] {
def construct(arg: A): T
}
trait Constructor2[T, A1, A2] {
def construct(arg1: A1, arg2: A2): T
}
def construct[T, A](arg1: A): T = implicitly[Constructor1[T, A]].construct(arg1)
...
This approach doesn't work though because it seems like in order to "summon" the Constructor type class instance, we need to write the types of the arguments, which is a lot of nasty boilerplate:
construct[Foo, String]("asd") // yuck!
Is there a way to use type classes (or anything else) to sort of partially infer the type parameters? We have the types of the constructor parameters for Foo defined in the Constructor instance definition, so if we can summon the instance we should be able to just call construct and get the right argument types. The issue is getting that instance without having to specify the constructor type arguments. I've played around with a bunch of different ideas for this, and I feel like with Scala's power and bag of tricks there just has to be a way I can write construct[Foo]("asd") and have the argument list be type safe. Any ideas?
UPDATE: Thanks to Miles Sabin's excellent answer + a slight modification, here's a method that only requires one type parameter and works for all different argument list lengths. This is a pretty simple way to painlessly wire up dependencies, without the cost of reflection:
trait Constructor1[T, A] { def construct(arg1: A)(implicit c: Container): T }
trait Constructor2[T, A, B] { def construct(arg1: A, arg2: B)(implicit c: Container): T }
implicit object FooConstructor extends Constructor1[Foo, String] {
def construct(arg1: String)(implicit c: Container) =
new Foo(arg1, c.getSingleton[FooService])
}
implicit object BarConstructor extends Constructor2[Bar, String, Int] {
def construct(arg1: String, arg2: Int)(implicit c: Container) =
new Bar(arg1, arg2, c.getSingleton[FooService])
}
class Construct[T] {
def apply[A](arg1: A)(implicit ctor: Constructor1[T, A], container: Container) =
ctor.construct(arg1)
def apply[A, B](arg1: A, arg2: B)(implicit ctor: Constructor2[T, A, B], container: Container) =
ctor.construct(arg1, arg2)
}
def construct[T] = new Construct[T]
construct[Foo]("asd")
construct[Bar]("asd", 123)
Type parameter inference in Scala is an all or nothing affair: if you explicitly supply any of the type arguments for a type parameter block then you must supply them all. Consequently, if you want to supply only some of a set of type arguments you must arrange for them to belong to separate type parameter blocks.
The way to do that in this case is to split the construct method into two stages: the first, which takes an explicit type argument and returns a function-like value; and a second, which applies the function-like value to the arguments for which you want the types to be inferred.
Here's how it might go,
// Function-like type
class Construct1[T] {
def apply[A](arg1: A)(implicit ctor : Constructor1[T, A]): T =
ctor.construct(arg1)
}
def construct[T] = new Construct1[T]
The result of invoking construct[Foo] is a value of type Construct1[Foo]. This has an apply method with a type parameter, which can be inferred, and an implicit parameter whose type is determined by both T and A. The invocation you want to make now looks like,
construct[Foo].apply("asd") // T explicit, A inferred as String
Scala's semantic sugaring rules around apply applies here which mean that this can be rewritten as,
construct[Foo]("asd")
which is exactly the result you want.
trait Construct[T, A] {
def apply(arg: A): T
}
class Constructor[T]{
def apply[A](arg : A)(implicit construct : Construct) = construct(arg)
}
object Constructor {
def apply[T] = new Constructor[T]
}
Constructor[T]("arg")