Trying to understand this scala notation - scala

I am new to Scala and while was trying to understand implicits in Scala, I am getting hard time understand [A](f: => A) part. Can any one explain please?
object Helpers {
implicit class IntWithTimes(x: Int) {
def times[A](f: => A): Unit = {
def loop(current: Int): Unit =
if(current > 0) {
f
loop(current - 1)
}
loop(x)
}
}
}
This is being called as:
scala> import Helpers._
import Helpers._
scala> 5 times println("HI")
HI
HI
HI
HI
HI
Reference : https://docs.scala-lang.org/overviews/core/implicit-classes.html

Let's disect this method declaration:
def times[A](f: => A): Unit
def: keyword used to define a method
times: method name
[A]: a type parameter named A. This means that this method takes a type parameter which can be passed either explicitly (e.g. by calling times[Int](...)) or implicitly (calling times(...) and letting compiler infer the type) when the method is called. See https://docs.scala-lang.org/tour/polymorphic-methods.html for more details
(f: => A): these are the method's "value parameters", in this case there's exactly one such parameter, named f, of type A (which is the type parameter we've declared!). The => signifies that this parameter is a call-by-name parameter, see https://docs.scala-lang.org/tour/by-name-parameters.html
: Unit: this is the method's return type - defined to be Unit, practically meaning this method doesn't return any value

Related

How to transfer type parameter through class methods in scala?

In my project, I need to write a generic class, which in a single method handles some types with its handler in a special way (Numeric is used for clarity in the example).
class A[T](val a:T){
def doSomething(b:T):T = a match{
case a : Int => doSomethingWithIntOrDouble(b)
case a : Double => doSomethingWithIntOrDouble(b)
case _ => b
}
def doSomethingWithIntOrDouble(b:T)(implicit ev:Numeric[T]):T =
ev.plus(a,b)
}
<console>:13: error: could not find implicit value for parameter ev: Numeric[T]
case a : Int => doSomethingWithIntOrDouble(b)
^
<console>:14: error: could not find implicit value for parameter ev: Numeric[T]
case a : Double => doSomethingWithIntOrDouble(b)
I think this happens because the compiler picks up the type parameter but not the actual one. Tell me, is there any way around this?
PS Okay If we assume that the answer is correct, then it is necessary to overload the dosomething method to achieve polymorphism.
class A[T](val a:T){
def doSomething(b:T)(implicit ev:Numeric[T]):T = ev.plus(a,b)
def doSomething(b:T):T = b
}
But in this case, another problem arises.
scala> a.doSomething(2)
<console>:13: error: ambiguous reference to overloaded definition,
both method doSomething in class A of type (b: Int)Int
and method doSomething in class A of type (b: Int)(implicit ev: Numeric[Int])Int
match argument types (Int)
a.doSomething(2)
I am not completely sure this is want your want, but I hope it helps.
Basically, you need to forward the evidence that the T type is a Numeric to the outer method. But, you also have to handle the case where it is not.
For that case, you can provide a default value for the implicit parameter like this:
class A[T](val a: T) {
def doSomething(b: T)(implicit ev: Numeric[T] = null): T = Option(ev) match {
case Some(ev) => doSomethingWithNumeric(b)(ev)
case None => b
}
def doSomethingWithNumeric(b: T)(implicit ev: Numeric[T]): T =
ev.plus(a, b)
}
It seems to work.
(new A(10)).doSomething(100) // res: Int = 110
(new A("hey")).doSomething("world") // res: String = "world"
Note that, if you will have many methods, maybe a cleanest solution would be to make A a trait with two implementations, one for numeric types and other for no numeric types.
Make the constructors of both sub classes private and create a factory for A in the companion object which ask for the implicit numeric parameter, and if found it will return a new instance of the numeric subclass.

Scala implicit conversion for type aliases

Define
type TA[T] = T => Int
implicit class TAOps[T](a: TA[T]) {
def foo(): Unit = {println("TA")}
}
val ta: TA[Double] = x => x.toInt
Now,
ta.foo()
fails to compile with the message value foo is not a member of ammonite.$sess.cmd1.TA[Double],
while the explicit call
TAOps(ta).foo()
prints TA. Why does the implicit conversion not work in the former case?
Your implicit def is expecting a type that receives one type parameter, i.e. a TA[T]
Your declaration: val ta: TA[Double] = ... is a type it self, and doesn't take any type parameters. So the compiler will not use your implicit def to type check this.
Conclusion you have an implicit type conversion for a type that takes a type parameter and TA[Double] doesn't take any type parameters.
Solutions:
1 - Replace the implicit type conversion to receive a Function1:
implicit class TAOps[T](a: T => Int) {
def foo: Unit = {
println("TA")
}
}
2 - Use type lambdas:
implicit class TAOps[T](a: ({type Alias = TA[T]})#Alias) {
def foo: Unit = {
println("TA")
}
}
Here the type you created is curried. So the compiler will now apply this implicit conversions to types that match, it is no longer expecting a type that receives 1 type parameter.
More on Type Lambdas

Scala generics not clear to me

class A {
def x(): Unit = {
println("tftf")
}
}
def t[A](x: A): Unit = {
x.x // <- error at this line
}
I get compile error - type mismatch; found : x.type (with underlying type A) required: ?{def x: ?} Note that implicit conversions are not applicable because they are ambiguous: both method any2Ensuring in object Predef of type [A](x: A)Ensuring[A] and method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A] are possible conversion functions from x.type to ?{def x: ?}
- t
Can someone explain this in English, please? I am new to Scala.
t's generic parameter named A shadows the class named A.
What you've written is equivalent to:
class A {
def x(): Unit = {
println("tftf")
}
}
def t[B](x: B): Unit = {
x.x // <- error at this line
}
In your example, A is a concrete type (a class). But in the function t[A](x: A): Unit, you're trying to use it as a type parameter. There's nothing generic about it.
A simple example of using generics with the function would be something like:
def t[A](x: A): Unit = println("Here is the parameter x: " + x)
This function will accept any type, and simply print it to the console.
in your def t[A](x: A), A is a generic type parameter and has nothing to do with the class A you defined. you can name it whatever you want, like def t[T](x: T).
what you want to do actually is:
def t[B <: A](x: B): Unit = {
x.x // won't error
}
There are two sources of confusion here:
Your type parameter A shadows class type A.
Type parameter A is unconstrained, which implicitly means [A <: Any], and Any doesn't have the member x. The confusing error message comes from the compiler attempting to apply an implicit conversion from Any to something that has a member x.
You simply want a function that takes a parameter that is a subtype of A, but you don't need a type parameter for this since any subtype of class type A is a valid substitution for class type A as a function parameter.
Hence the solution is simply this:
def t(a: A) {
a.x()
}

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
}
}

Why does Scala type inference fail here?

I have this class in Scala:
object Util {
class Tapper[A](tapMe: A) {
def tap(f: A => Unit): A = {
f(tapMe)
tapMe
}
def tap(fs: (A => Unit)*): A = {
fs.foreach(_(tapMe))
tapMe
}
}
implicit def tapper[A](toTap: A): Tapper[A] = new Tapper(toTap)
}
Now,
"aaa".tap(_.trim)
doesn't compile, giving the error
error: missing parameter type for expanded function ((x$1) => x$1.trim)
Why isn't the type inferred as String? From the error it seems that the implicit conversion does fire (otherwise the error would be along the lines of "tap is not a member of class String"). And it seems the conversion must be to Tapper[String], which means the type of the argument is String => Unit (or (String => Unit)*).
The interesting thing is that if I comment out either of tap definitions, then it does compile.
6.26.3 Overloading Resolution
One first determines the set of
functions that is potentially
applicable based on the shape of the
arguments
...
If there is precisely one alternative
in B, that alternative is chosen.
Otherwise, let S1, . . . , Sm be the
vector of types obtained by typing
each argument with an undefined
expected type.
Both overloads of tap are potentially applicable (based on the 'shape' of the arguments, which accounts for the arity and type constructors FunctionN).
So the typer proceeds as it would with:
val x = _.trim
and fails.
A smarter algorithm could take the least upper bound of the corresponding parameter type of each alternative, and use this as the expected type. But this complexity isn't really worth it, IMO. Overloading has many corner cases, this is but another.
But there is a trick you can use in this case, if you really need an overload that accepts a single parameter:
object Util {
class Tapper[A](tapMe: A) {
def tap(f: A => Unit): A = {
f(tapMe)
tapMe
}
def tap(f0: A => Unit, f1: A => Unit, fs: (A => Unit)*): A = {
(Seq(f0, f1) ++ fs).foreach(_(tapMe))
tapMe
}
}
implicit def tapper[A](toTap: A): Tapper[A] = new Tapper(toTap)
"".tap(_.toString)
"".tap(_.toString, _.toString)
"".tap(_.toString, _.toString, _.toString)
}