So I'm following fpinscala and I have this Object:
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 sum(ints: List[Int]): Int = ints match {
case Nil => 0
case Cons(x, xs) => x + sum(xs)
}
def product(ds: List[Double]): Double = ds match {
case Nil => 1
case Cons(x, xs) => x * product(xs)
}
def apply[A](as: A*): List[A] =
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
def tail[A](as: List[A]): List[A] = as match {
case Nil => as
case Cons(_, xs) => xs
}
def setHead[A](as: List[A], a: A): List[A] = as match {
case Nil => Cons(a, Nil)
case Cons(_, xs) => Cons(a, xs)
}
def main(args: Array[String]): Unit =
println(tail(List(1,2,3)))
}
When I try to run main I get:
error: type mismatch;
found : List[Int] (in scala.collection.immutable)
required: List[?] (in <empty>)
println(tail(List[Int](1,2,3)))
I have followed the book pretty exactly so I don't know what I'm missing here. It says you should now be able to call List(1, 2, 3, 4) or List("hello", "goodbye") with no issues. But I can't pass that to the function? Some insight on what I'm missing would be appreciated.
The code compiles correctly, the only problem I see is that you are declaring the main method in the List companion object and that is incorrect, you should move it to other object:
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 sum(ints: List[Int]): Int = ints match {
case Nil => 0
case Cons(x, xs) => x + sum(xs)
}
def product(ds: List[Double]): Double = ds match {
case Nil => 1
case Cons(x, xs) => x * product(xs)
}
def apply[A](as: A*): List[A] =
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
def tail[A](as: List[A]): List[A] = as match {
case Nil => as
case Cons(_, xs) => xs
}
def setHead[A](as: List[A], a: A): List[A] = as match {
case Nil => Cons(a, Nil)
case Cons(_, xs) => Cons(a, xs)
}
}
object Main {
def main(args: Array[String]): Unit =
println(List.tail(List(1,2,3)))
}
Related
I'm working on writing the Stream class in Chapter 5 of Functional Programming in Scala, I know the solutions are online, but it's not helping me. I faced the same issue with the previous Chapter writing the List class.
I got so frustrated I actually COPY PASTED from the solution to my Scala worksheet and still the same issue.
I thought maybe it's because of the name (there's already a List and Stream), doesn't seem like a smart idea to name them like this, so I changed it, didn't help.
Maybe it's something to do with Intellij (I'm using IntelliJ IDEA), I'm doing the exercises on the Scala Worksheets. But I can't find anything about this issue in relation to IDEs.
Here is what I have so far:
sealed trait StreamRED[+A]
case object Empty extends StreamRED[Nothing]
case class Cons[+A](h: () => A, t: () => StreamRED[A]) extends StreamRED[A]
object StreamRED {
def cons[A](hd: => A, tl: => StreamRED[A]): StreamRED[A] = {
lazy val head = hd
lazy val tail = tl
Cons(() => head, () => tail)
}
def empty[A]: StreamRED[A] = Empty
def apply[A](as: A*): StreamRED[A] =
if (as.isEmpty) empty else cons(as.head, apply(as.tail: _*))
def headOption: Option[A] = this match {
case Empty => None
case Cons(h,t) => Some(h())
}
def toList: List[A] = {
#annotation.tailrec
def go(s: StreamRED[A], acc: List[A]): List[A] = s match {
case Cons(h,t) => go(t(), h() :: acc)
case _ => acc
}
go(this, List()).reverse
}
}
I get the following errors:
"Cannot resolve symbol A" on the A in Option[A] (in headOption method) and List[A] and StreamRED[A] (in toList)
"Type mismatch. Required: StreamRED[Any], Found: StreamRED.type" on the this in toList.
"Pattern type is incompatible with expected type, found: Empty.type, required: StreamRED.type" on the Empty in headOption.
New to Scala, new to IntelliJ, new to statically typed languages, new to FP. Any explanations and recommendations for good reading materials much appreciated.
The two functions toList and headOption cannot be defined in the companion object of StreamRED.
If you define them directly in the trait it works:
sealed trait StreamRED[+A] {
def headOption: Option[A] = this match {
case Empty => None
case Cons(h,t) => Some(h())
}
def toList: List[A] = {
#annotation.tailrec
def go(s: StreamRED[A], acc: List[A]): List[A] = s match {
case Cons(h,t) => go(t(), h() :: acc)
case _ => acc
}
go(this, List()).reverse
}
}
case object Empty extends StreamRED[Nothing]
case class Cons[+A](h: () => A, t: () => StreamRED[A]) extends StreamRED[A]
object StreamRED {
def cons[A](hd: => A, tl: => StreamRED[A]): StreamRED[A] = {
lazy val head = hd
lazy val tail = tl
Cons(() => head, () => tail)
}
def empty[A]: StreamRED[A] = Empty
def apply[A](as: A*): StreamRED[A] =
if (as.isEmpty) empty else cons(as.head, apply(as.tail: _*))
}
A word of warning: Pattern matching on this is feels to me like bad practice. You know exactly what this is. Implement the functions in Empty and Cons instead.
Do this instead:
sealed trait StreamRED[+A] {
def headOption: Option[A]
def toList: List[A]
}
case object Empty extends StreamRED[Nothing] {
def headOption: Option[Nothing] = None
def toList: List[Nothing] = List()
}
case class Cons[+A](h: () => A, t: () => StreamRED[A]) extends StreamRED[A] {
def headOption: Option[A] = Some(h())
def toList: List[A] = h() +: t().toList
}
object StreamRED {
def cons[A](hd: => A, tl: => StreamRED[A]): StreamRED[A] = {
lazy val head = hd
lazy val tail = tl
Cons(() => head, () => tail)
}
def empty[A]: StreamRED[A] = Empty
def apply[A](as: A*): StreamRED[A] =
if (as.isEmpty) empty else cons(as.head, apply(as.tail: _*))
}
I'm working through the book Functional Programming in Scala, and at the end of the data structures chapter you are asked to implement the filter method in terms of flatMap. Here are the necessary functions and implementations:
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: _*))
}
def append[A](l1: List[A], l2: List[A]): List[A] = {
foldRight(l1, l2)((elem, acc) => Cons(elem, acc))
}
def concat[A](ls: List[List[A]]): List[A] = {
foldLeft(ls, Nil: List[A])(append)
}
def map[A, B](l: List[A])(f: A => B): List[B] = {
foldRight(l, Nil: List[B])((elem, acc) => Cons(f(elem), acc))
}
def filter[A](l: List[A])(f: A => Boolean): List[A] = {
List.flatMap(l)(a => if (f(a)) List(a) else Nil)
}
def flatMap[A, B](l: List[A])(f: A => List[B]): List[B] = {
concat(map(l)(f))
}
def foldRight[A, B](l: List[A], z: B)(f: (A, B) => B): B = {
l match {
case Nil => z
case Cons(h, t) => f(h, foldRight(t, z)(f))
}
}
def foldLeft[A, B](l: List[A], z: B)(f: (B, A) => B): B = {
l match {
case Nil => z
case Cons(h, t) => foldLeft(t, f(z, h))(f)
}
}
}
The actual function call is here:
val x = List(1, 2, 3, 4, 5)
List.filter(x)(_ < 3)
As far as I can follow, after the map step you will have a List that looks like this:
Cons(Cons(1, Nil), Cons(2, Nil), Cons(Nil, Nil)...
I'm having trouble seeing where elements that are Nil are filtered out from the final result.
They are not "filtered out". They simply disappear after you apply concat on the list of lists, because concatenation with an empty list does nothing.
I am trying to implement List(the below code) and I am getting the error mentioned in the title.
From the error I understand that :: method should take type T but actually it is given as List[T]. Or I guess it is expecting to create an apply method.
object List {
def apply[T](x1: T, y1: T) = new Cons(x1, new Cons(y1, Nil))
def apply[T]() = Nil
def apply[T](x2: T) = new Cons(x2, Nil)
}
trait List[+T]{
def isEmpty : Boolean
def head : T
def tail : List[T]
def prepend [U >: T ] (elem : U) : List[U] = new Cons(elem, this)
override def toString = if (this.isEmpty) "." else "{" + head + tail + "}"
def isort [U >: T](xs: List[U]) : List[U] = xs match {
case Nil => Nil
case y :: ys => insert(y,isort(ys))
}
def :: [U >: T ] (elem: U) : List[U] = new Cons(elem, this)
def insert[U >: T](y: T, ys: List[T]) : List[T] = ys match {
case Nil => List(y)
case x :: xs => if (y <= x) y :: ys else x :: insert(y , xs)
}
}
class Cons[T](val head: T, val tail: List[T]) extends List[T]{
def isEmpty = false
}
object Nil extends List[Nothing]{
def isEmpty = true
def head: Nothing = throw new Error("head.List")
def tail: Nothing = throw new Error("tail.List")
}
Please suggest what parameter should the apply method have.
I've tried to repair it... It's too broken. I will therefore only enumerate the main error sources:
Case classes: Neither Nil nor Cons were case classes, why do you match on them?
Extractors: You have neither a case-class ::, nor any extractor called ::, so you can't pattern match on x :: xs. Use your own Cons(x, xs) instead
Ordering: You can't call <= on arbitrary elements, you need an Ordering somewhere in scope
Insert: The signature of insert didn't make any sense, it takes too many arguments.
Here is a compilable (but probably still very incorrect) version:
object List {
def apply[T](x1: T, y1: T) = new Cons(x1, new Cons(y1, Nil))
def apply[T]() = Nil
def apply[T](x2: T) = new Cons(x2, Nil)
}
import scala.math.Ordering
trait List[+T]{
def isEmpty : Boolean
def head : T
def tail : List[T]
def prepend [U >: T] (elem : U) : List[U] = new Cons(elem, this)
override def toString = if (this.isEmpty) "." else "{" + head + tail + "}"
def isort [U >: T](xs: List[U])(implicit ord: Ordering[U]): List[U] = xs match {
case Nil => Nil
case Cons(y, ys) => this.isort(ys).insert(y)
}
def :: [U >: T] (elem: U) : List[U] = new Cons(elem, this)
def insert[U >: T](y: U)(implicit ord: Ordering[U]): List[U] = {
import ord._
this match {
case Nil => List(y)
case Cons(x, xs) => if (y <= x) Cons(y, xs.insert[U](x)) else Cons(x, xs.insert(y))
}
}
}
case class Cons[T](val head: T, val tail: List[T]) extends List[T] {
def isEmpty = false
}
case object Nil extends List[Nothing] {
def isEmpty = true
def head: Nothing = throw new Error("head.List")
def tail: Nothing = throw new Error("tail.List")
}
I hope it contains enough hints so you can repair the rest.
B is a super class of A , then as per scala variants and covariants . variant type can occur at parameter and covariant type can occur at function return type
My scala class make method is taking B type in paramters and returning subtype A as function type but as per function "make" it is correct but if i have companion class like case class for same class which is generic in A is giving error. I spent enough time to correct this error but not able to do so.
sealed class myList[+A] {
def apply[A](as: A*): myList[A] ={
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}
def head():A = this.head
def tail():myList[A] = this.tail
def isEmpty():Boolean ={
this match {
case Nil => true
case _: myList[A] => false
}
}
def preappend[B>:A](x: B): myList[A] ={
if (isEmpty) make(x)
else make(x)
}
def append[B>:A](x: B): myList[A] ={
if (this.isEmpty) make(x)
else Cons(this.head,this.tail.append(x))
}
def print()={
this.map(println)
}
def make[B>:A](x:B): myList[A] ={
this match {
case Nil => Cons(x,Nil)
case Cons(xh, xs) => Cons(xh, xs.make(x))
}
}
def map[A,B](f: (A) => B): myList[B] = {
this match {
case Nil => Nil
case Cons(xh:A, xs:myList[A]) => Cons(f(xh),xs.map(f ))
}
}
/**
* Combines all elements of this list into value.
*
* Time - O(n)
* Space - O(n)
*/
def fold[B](n: B)(op: (B, A) => B): B = {
def loop(l: myList[A], a: B): B =
if (l.isEmpty) a
else loop(l.tail, op(a, l.head))
loop(this, n)
}
def foldLeft[B](z: B)(f: (B, A) => B): B = {
var acc = z
var these = this
while (!these.isEmpty) {
acc = f(acc, these.head)
these = these.tail
}
acc
}
def foldRight[B,A](z: B)(f: (A, B) => B): B = this match {
case nil=> z
case Cons(x:A,xs:myList[A])=>f(x, foldRight(z)(f))
}
def length[B>:A](lst:myList[B]):Int={
this.foldRight(0) {( lst:myList[A],x:Int) => lst match{
case nil=>x
case _: myList[B] => x+1
}
}
}
def fail(m: String) = throw new NoSuchElementException(m)
}
case object Nil extends myList[Nothing] {
override def head: Nothing = fail("An empty list.")
override def tail: myList[Nothing] = fail("An empty list.")
override def isEmpty: Boolean = true
}
case class Cons[-A](head: A, tail: myList[A]) extends myList[A] {
override def isEmpty: Boolean = false
}
case class truck(
numberPlate:String
)
object Main {
def main(args: Array[String]) {
val a= new truck("1233bsd")
val b = new truck("dsads334")
val c = new myList[truck]
c.append(a)
c.print()
c.append(b)
c.print()
}
}
error i am getting:-
mylist-v2.scala:40: error: type mismatch;
found : x.type (with underlying type B)
required: A
case Nil => Cons(x,Nil)
^
mylist-v2.scala:50: warning: abstract type pattern A is unchecked since it is eliminated by erasure
case Cons(xh:A, xs:myList[A]) => Cons(f(xh),xs.map(f ))
^
mylist-v2.scala:50: warning: abstract type A in type pattern myList[A] is unchecked since it is eliminated by erasure
case Cons(xh:A, xs:myList[A]) => Cons(f(xh),xs.map(f ))
^
mylist-v2.scala:79: warning: abstract type pattern A is unchecked since it is eliminated by erasure
case Cons(x:A,xs:myList[A])=>f(x, foldRight(z)(f))
^
mylist-v2.scala:79: warning: abstract type A in type pattern myList[A] is unchecked since it is eliminated by erasure
case Cons(x:A,xs:myList[A])=>f(x, foldRight(z)(f))
^
four warnings found
one error found
I think the minimal changes to make this code compile is to change Cons to
case class Cons[+A](override val head: A, override val tail: myList[A]) extends myList[A] {
and signatures of prepend, append and make to
def preappend[B>:A](x: B): myList[B] ={
def append[B>:A](x: B): myList[B] ={
def make[B>:A](x:B): myList[B] ={
As you didn't describe your actual goal, it is hard to say whether this is what you really want or not.
I tried to implement mergesort in Scala. I got to the following:
def mergeSort[A: Ordering](as: List[A]): List[A] = as match {
case Nil => as
case head :: Nil => as
case _ => {
val (l, r) = split(as)
merge(mergeSort(l), mergeSort(r))
}
}
def split[A](as: List[A]): (List[A], List[A]) = {
def rec(todo: List[A], done: (List[A], List[A])): (List[A], List[A]) = todo match {
case Nil => done
case head :: tail => rec(tail, (head :: done._2, done._1))
}
rec(as, (Nil, Nil))
}
def merge[A: Ordering](left: List[A], right: List[A]) = {
def rec(left: List[A], right: List[A], done: List[A]): List[A] =
(left, right) match {
case (_, Nil) => rprepend(left, done)
case (Nil, _) => rprepend(right, done)
case (lh :: lt, rh :: rt) => if (implicitly[Ordering[A]].compare(lh, rh) <= 0)
rec(lt, right, lh :: done)
else rec(left, rt, rh :: done)
}
rec(left, right, Nil).reverse
}
def rprepend[A](prepend: List[A], as: List[A]): List[A] =
prepend.foldLeft(as)((r, a) => a :: r)
This question is not about the obscene amount of inefficient reversing going on, nor about the lack of tail recursion. Rather, I noticed that you could generalize mergesort by passing in a sort algorithm like so:
def generalizedMergeSort[A: Ordering](as: List[A], sort: List[A] => List[A]): List[A] = as match {
case Nil => as
case head :: Nil => as
case _ => {
val (l, r) = split(as)
merge(sort(l), sort(r))
}
}
Then I tried re-implementing mergesort as
def mergesort[A: Ordering](as: List[A]): List[A] = {
generalizedMergeSort(as, mergesort)
}
but this fails to compile, not finding the proper Ordering[A]:
[error] test.scala:17: No implicit Ordering defined for A.
[error] generalizedMergeSort(as, mergesort)
[error] ^
as a feeble attempt to get things in scope I tried
def mergesort[A: Ordering](as: List[A]): List[A] = {
implicit val realythere = implicitly[Ordering[A]]
generalizedMergeSort(as, mergesort)
}
but to no avail.
I suspect the problem may be in the second parameter of generalizedMergesort. I say the parameter is a List[A] => List[A], but I pass in a List[A] => implicit Ordering[A] => List[A] but I don't know how to make use of that to get to my goal of implementing mergesort in terms of generalizedMergesort and itself.
You can overcome this by passing a function that calls mergesort to generalizedMergeSort. This call will capture the implicit Ordering:
def mergesort[A: Ordering](as: List[A]): List[A] = {
generalizedMergeSort(as, mergesort(_: List[A]))
}
mergesort(_: List[A]) is a closure function of type List[A] => List[A], which calls mergesort with its argument, and the implicit Ordering argument gets captured in this closure.
The simple solution is to extract implicit from method to upper method:
def mergesort[A: Ordering](as: List[A]): List[A] = {
def mergesort0(xs: List[A]): List[A] = generalizedMergeSort(xs, mergesort0)
mergesort0(as)
}
and second is to wrap your function with implicit (with additional object creation):
def mergesort[A: Ordering](as: List[A]): List[A] = {
val mergesort0: List[A] => List[A] = xs => mergesort(xs)
generalizedMergeSort(as, mergesort0)
}