What is A* for method parameter? - scala

In below apply method what is "as: A*" ?
List(1, 2, 3) constucts a List of type : Cons(1,Cons(2,Cons(3,Nil)))
From reading the method code it appears that its a kind of syntax sugar for
multiple type parameters of same type ?
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
object List {
def apply[A](as: A*): List[A] =
if (as.isEmpty) Nil
else {
Cons(as.head, apply(as.tail: _*))
}
}
If this is true should'nt this be also valid :
object List {
def apply[A](asHead: A , asTail : A): List[A] =
if (asHead.isEmpty) Nil
else {
Cons(asHead.head, apply(asTail.tail: _*))
}

No, there's a difference here.
When you declare asHead: A, asTail: A, asHead and asTail have obviously the same type. However, in the original code that uses as: A*, the type of as.head is A, and the type of as.tail is Seq[A] -- as can be deduced from the types of head and tail. Therefore, your code is not the same thing.
The declaration A* stands for "a variable number of parameters of type A", usually known as vararg. This is similar to a Seq[A], but differ in the invocation:
apply(1, 2, 3) // A*
apply(Seq(1, 2, 3)) // Seq[A]
The counterpart to that is the : _* declaration when calling a vararg method with a sequence:
apply(Seq(1, 2, 3): _*) // A*
apply(Seq(1, 2, 3)) // Seq[A]

Related

Please help to explain a case of Scala constructor and companion object

I think that I would make some mistakes in below explanation for my question
but within my limit understanding I cannot figure out how to correctly describe the issue
The scala code snipet as below:
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
object List {
def apply[A](as: A*):List[A] =
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}
If I create object x as:
val x = List(1,2,3)
I pass into companion object "List", three numbers as : 1 ,2 and 3
Then, internally, function apply is triggered
At the moment of construction, how could these three numbers has method/attribute like: as.head and as.tail
I guess it could be possibly a kind of pattern matching, but even that, I could not understand the magic that number "as" now has method/attribute for ".head" and ".tail"
Try this in the REPL.
scala> def apply[A](as :A*) = as
apply: [A](as: A*)Seq[A]
So the compiler considers the varargs variable, as, to be of type Seq[A], which is where the .head and .tail comes from.
The trick is that as: A* is a variable argument what is converted to an array-like object, actually a WrappedArray$ofInt in your case.
WrappedArray has head and tail methods.
You can extend your definition of List object to see A*'s class like this:
object List {
def apply[A](as: A*):List[A] = {
println(as.getClass)
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}
}
For a more detailed explanation check e.g. this .

Scala Type mismatch, expected: List[NotInferedA], actual: List[Int]

I'm trying to execute this piece of code inside a Scala Worksheet (using Intellij):
Scala version I'm using is 2.11.12
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
def tail[A](l: List[A]): List[A] =
l match {
case Nil => sys.error("tail of empty list")
case Cons(_, t) => t
}
val a = List(1,2,3)
tail(a) //should be List(2,3)
The compiler gives me a 'Type mismatch, expected: List[NotInferedA], actual: List[Int].
Can someone help me?
Thanks
Your List class is missing a companion object. Calling List(1,2,3) constructs a default Scala List, not your list.
You need to add something like this (replace ??? with the real constructor functionality, probably using some recursive function):
object List {
def apply[A](s: A*) = ???
}

Scala List with type parameter

I had a problem coding a function called head, that basically replace the head elements with another for the List invoking it:
List(1,2,3,4).head(4) // List(4,2,3,4)
The code is obviously useless, I was just trying to have fun with Scala. This is the code:
sealed trait List[+A]{
def tail():List[A]
def head[A](x:A):List[A]
}
object Nil extends List[Nothing]{
def tail() = throw new Exception("Nil couldn't has tail")
def head[A](x:A): List[A] = List(x)
}
case class Cons[+A](x :A, xs: List[A]) extends List[A]{
def tail():List[A] = xs
def head[A](a:A): List[A] = Cons(a,xs)
}
object List{
def apply[A](as:A*):List[A] = {
if (as.isEmpty) Nil
else Cons(as.head,apply(as.tail: _*))
}
}
Cons(1,Cons(2,Nil)) == List(1,2)
Cons(1,Cons(2,Cons(3,Cons(4,Nil)))).tail()
List(1,2,3,4,5,6,7).tail()
List(1,2,3,4).head(4)
It doesn't not compile and I have this error:
Error:(11, 39) type mismatch;
found : A$A318.this.List[A(in class Cons)]
required: A$A318.this.List[A(in method head)]
def head[A](a:A): List[A] = Cons(a,xs)
Could you explain why, please?
Regards.
Your problem is that your head method is taking another type A, therefore inside that scope the compiler takes those As as different, i.e., the A defined in the trait is shadowed by the A in head[A].
Also, your head method is taking a covariant element of type A in a contravariant position, so you can't define head as such.
What you can do is defining your head as:
def head[B >: A](x: B): List[B]
Hence, you get:
object S {
sealed trait List[+A] {
def tail(): List[A]
def head[B >: A](x: B): List[B]
}
case object Nil extends List[Nothing] {
def tail() = throw new Exception("Nil doesn't have a tail")
def head[B >: Nothing](x: B): List[B] = Cons(x, Nil)
}
case class Cons[+A](x: A, xs: List[A]) extends List[A] {
def tail(): List[A] = xs
def head[B >: A](a: B): List[B] = Cons(a, xs)
}
object List {
def apply[A](as: A*): List[A] = {
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}
}
}
Testing this on the REPL:
scala> :load test.scala
Loading test.scala...
defined object S
scala> import S._
import S._
scala> Nil.head(1)
res0: S.List[Int] = Cons(1,Nil)
scala> Cons(1, Nil).head(4)
res1: S.List[Int] = Cons(4,Nil)
You method head does not need a type parameter, since you already have one defined in the class definition and that is exactly the type you want head to receive (if you want head to create a list of the same type of the original).
The error you get is because A is two different types in the context of the method head (the one from the method and the other from the class).
The definition for head should be:
def head(x:A):List[A]

Creating own List replica in Scala

I am reading Functional Programming in Scala from Manning, authored by Paul Chiusano and Runar Bjarnason. In its 3rd chapter, there is a code to create a List and there are assignments to implement various methods of the list. Following is partial implementation of the my List
package src.Cons
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](h:A, t:List[A]) extends List[A]
object List {
//my issue is I do not want to pass a list to sum but want to use objectName.sum notation
def sum(ints:List[Int]):Int = ints match {
case Nil => 0
case Cons(x,xs) => x+sum(xs)
}
}
Question - How can I create my list such that I can call l.sum instead of List.sum(l)?
You can "PmL", as #Gabriele Petronella has suggested, or you can move the sum() method to the Cons class, as #DeadNight wrote, but before either of those can work you have to resolve the current conflict between your List object and your List trait.
The sum() in your List object can only sum a List[Int] but your class definitions use a more generic type member and, as such, you can't use + because the compiler doesn't know how to add two A types.
If you want to restrict your List to only handling numeric types then this will work.
case class Cons[A: Numeric](h:A, t:List[A]) extends List[A] {
def sum: A = List.sum(this)
}
object List {
def sum[A](ints:List[A])(implicit ev: Numeric[A]):A = ints match {
case Nil => ev.zero
case Cons(x,xs) => ev.plus(x, sum(xs))
}
}
val x = Cons(4, Cons(2, Nil))
x.sum // res0: Int = 6
Making sum a member
The problem is, you don't know how to sum the List[A] for every type A, only a List[Int]. If there was a way to allow calls when A is an Int...
Let's take a look at the standard library for that. We're interested in Option#flatten method because:
val o1 = Option(Option(3)).flatten // compiles
val o2 = Option(4).flatten // does not compile
Notice the weird implicit ev: <:<[A, Option[B]]. This is the key here - it's a thing that compiler provides for you, but only if it is known at compile time, that your Option[A] is a subtype of Option[Option[B]] for some type B. This is the trick that we can use.
sealed trait List[+A] {
def sum(implicit ev: A <:< Int): Int = this match {
case Nil => 0
case Cons(x, xs) => x + xs.sum // <- here x is magically converted to Int, so we can use plus
}
}
case object Nil extends List[Nothing]
case class Cons[+A](h:A, t:List[A]) extends List[A]
println(Cons(4, Cons(38, Nil)).sum) // 42
ScalaFiddle
Notice that you can write <:<[A, B] as A <:< B.
NB: there's also =:=[A, B] type, for when your A is exactly Int - you can use either of those
Doing better?
Actually, std library has sum method and it's type is even weirder:
def sum(implicit ev: Numeric[A]). Doing so allows it to work on any number-like type like Double and Int, and has the operations for comparison, subtraction, multiplication, etc. So you can make it even more generic. I suggest you do it after reading a chapter about Monoids, tho :)
You can use the so-called "Pimp my Library" pattern.
Define an implicit class ListOps
implicit class ListOps[+A](list: List[A]) {
def sum = List.sum(this)
}
and now you can call list.sum. The implicit conversion will be triggered and the compiler will interpret it as ListOps(list).sum.
Move the definition of sum inside the definition of List trait
You can leave the concrete definitions to Nil & Cons
package src.Cons
sealed trait List[+A] {
def sum: Int
}
case object Nil extends List[Nothing] {
val sum: Int = 0
}
case class Cons[+A](h:A, t:List[A]) extends List[A] {
def sum: Int = h + t.sum
}

Scala: "apply" method in companion are required to create case class instance?

The below code defines a List type and two implementation of case classes one representing empty list and Cons to create actual list
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
object List {
...
def apply[A](as: A*): List[A] = {
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}
val example = Cons(1, Cons(2, Cons(3, Nil)))
}
is my assumption correct that the list is created by the recursive apply method above when the val example = ... is executed.
if that is so. the signature for creating Cons is Cons(head, tail) where as the signature of the apply is incompatible variad def apply[A](as: A*): List[A], how does scala actually infers the val example to be List(1, 2, 3, Nil)
When you say
class Foo(s: String, i: Int)
in scala, it generates a class Foo with a constructor taking a String and an Int.
It's pretty much the same as a java class declared as
public class Foo {
public Foo(String s, int i) {
...
}
}
With case classes, the compiler provides extra-goodies such as a companion object with a default apply method taking the same parameters as the constructor.
So that's why you can directly call Cons(head, tail), without explicitly define a constructor.