Scala: methods in trait can't use methods from companion object - scala

When I try to compile the following I get:
"not found: value cons" and "not found: value empty" for the take and drop method definitions.
Somehow the trait doesn't "see" the companion object?
I'm using IntelliJ IDEA, in case that matters.
import scala.annotation.tailrec
object Run extends App {
sealed trait StreamRed[+A] {
def headOption: Option[A] = this match {
case Empty => None
case Cons(h,t) => Some(h())
}
def toList: List[A] = {
#tailrec
def toListRec(stream: StreamRed[A], accumulated: List[A]): List[A] = this match {
case Cons(h,t) => toListRec(t(), h()::accumulated)
case _ => accumulated
}
toListRec(this, List()).reverse
}
def take(n: Int): StreamRed[A] = this match {
case Cons(h, t) if n > 1 => cons(h(), t().take(n - 1))
case Cons(h, _) if n == 1 => cons(h(), empty)
case _ => empty
}
#tailrec
def drop(n: Int): StreamRed[A] = this match {
case Cons(_,t) if n > 0 => t().drop(n-1)
case _ => empty
}
}
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: _*))
}
}

Companions can see each other's members in the sense that access modifiers are not a problem.
class A {
private def foo: Unit = ()
A.bar
}
object A {
private def bar: Unit = ()
(new A).foo
}
is ok on contrary to
class A {
private def foo: Unit = ()
B.bar
}
object B {
private def bar: Unit = ()
(new A).foo
}
(But if you replace private with private[this] the former won't work either.)
But this doesn't mean that namespaces are imported automatically.
class A {
private def foo: Unit = ()
import A._
bar
}
object A {
private def bar: Unit = ()
val a = new A
import a._
foo
}
is ok on contrary to
class A {
private def foo: Unit = ()
bar
}
object A {
private def bar: Unit = ()
foo
}
Anyway a method has to know its this.

Related

Scala type mismatch, cannot resolve symbol A, Pattern type is incompatible with expected type

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: _*))
}

scala variant type causes error type mismatch error

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.

scala forward reference extends over definition

case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
sealed trait Stream[+A] {
def toList: List[A] = {
val buf = new collection.mutable.ListBuffer[A]
def go(s: Stream[A]): List[A] = s match {
case Cons(h, t) =>
buf += h()
go(t())
case _ => buf.toList
}
go(this)
}
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = Stream.cons(hd, tl)
def empty = Stream.empty
def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] = f(z) match {
case Some((h,t)) => cons(h, unfold(t)(f))
case None => empty
}
def take(n: Int): Stream[A] = unfold((this, n)) {
case (Cons(h, t), 1) => Some((h(), (empty, 0)))
case (Cons(h, t), n) if n > 1 => Some((h(), (t(), n-1)))
case (Empty, 0) => None
}
}
object Stream {
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = Cons(() => hd, () => tl)
def empty[A]: Stream[A] = Empty
val ones: Stream[Int] = Stream.cons(1, ones)
}
object StreamTest {
def main(args: Array[String]) {
//why compile error: forward reference extends over definition of value ones
/*val ones: Stream[Int] = Stream.cons(1, ones)
println(ones.take(5).toList)*/
println(Stream.ones.take(5).toList)
}
}
why compile error?: forward reference extends over definition of value ones
in pair object 'Stream',
val ones: Stream[Int] = Stream.scons(1, ones) is ok
but in main method, it's not ok (but... same synthetics!)
Local vals are not members.
For your test code, do this:
object StreamTest extends App {
//def main(args: Array[String]) {
//why compile error: forward reference extends over definition of value ones
val ones: Stream[Int] = Stream.cons(1, ones)
println(ones.take(5).toList)
println(Stream.ones.take(5).toList)
//}
}
The restriction in blocks is worded in the spec here, where the other advice is to make it a lazy val in the block, which has the same effect.
The forward reference is in Cons[+A]...which is referenced in this line:
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = Cons(() => hd, () => tl)
Try to move
case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
into the companion object.

What is the purpose of the emptyCoproduct and coproduct methods of the TypeClass trait in Shapeless

It is not fully clear to me what is the purpose of the emptyCoProduct and coproduct methods of the TypeClass trait in Shapeless.
When would one use the TypeClass trait instead of the ProductTypeClass?
What are some examples of ways those two methods would be implemented?
Suppose I've got a simple type class:
trait Weight[A] { def apply(a: A): Int }
object Weight {
def apply[A](f: A => Int) = new Weight[A] { def apply(a: A) = f(a) }
}
And some instances:
implicit val stringWeight: Weight[String] = Weight(_.size)
implicit def intWeight: Weight[Int] = Weight(identity)
And a case class:
case class Foo(i: Int, s: String)
And an ADT:
sealed trait Root
case class Bar(i: Int) extends Root
case class Baz(s: String) extends Root
I can define a ProductTypeClass instance for my type class:
import shapeless._
implicit object WeightTypeClass extends ProductTypeClass[Weight] {
def emptyProduct: Weight[HNil] = Weight(_ => 0)
def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
Weight { case (h :: t) => hw(h) + tw(t) }
def project[F, G](w: => Weight[G], to: F => G, from: G => F): Weight[F] =
Weight(f => w(to(f)))
}
And use it like this:
scala> object WeightHelper extends ProductTypeClassCompanion[Weight]
defined object WeightHelper
scala> import WeightHelper.auto._
import WeightHelper.auto._
scala> implicitly[Weight[Foo]]
res0: Weight[Foo] = Weight$$anon$1#4daf1b4d
scala> implicitly[Weight[Bar]]
res1: Weight[Bar] = Weight$$anon$1#1cb152bb
scala> implicitly[Weight[Baz]]
res2: Weight[Baz] = Weight$$anon$1#74930887
But!
scala> implicitly[Weight[Root]]
<console>:21: error: could not find implicit value for parameter e: Weight[Root]
implicitly[Weight[Root]]
^
This is a problem—it makes our automated type class instance derivation pretty much useless for ADTs. Fortunately we can use TypeClass instead:
implicit object WeightTypeClass extends TypeClass[Weight] {
def emptyProduct: Weight[HNil] = Weight(_ => 0)
def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
Weight { case (h :: t) => hw(h) + tw(t) }
def project[F, G](w: => Weight[G], to: F => G, from: G => F): Weight[F] =
Weight(f => w(to(f)))
def emptyCoproduct: Weight[CNil] = Weight(_ => 0)
def coproduct[L, R <: Coproduct]
(lw: => Weight[L], rw: => Weight[R]): Weight[L :+: R] = Weight {
case Inl(h) => lw(h)
case Inr(t) => rw(t)
}
}
And then:
scala> object WeightHelper extends TypeClassCompanion[Weight]
defined object WeightHelper
scala> import WeightHelper.auto._
import WeightHelper.auto._
scala> implicitly[Weight[Root]]
res0: Weight[Root] = Weight$$anon$1#7bc44e19
All the other stuff above still works as well.
To sum up: Shapeless's Coproduct is a kind of abstraction over ADTs, and in general you should provide instances of TypeClass for your type classes instead of just ProductTypeClass whenever possible.
As of shapeless 2.3.2, the above example doesn't seem to compile. here's the updated one for future reference:
import shapeless._
import shapeless.test._
trait Weight[A] { def apply(a: A): Int }
object Weight {
def apply[A](f: A => Int) = new Weight[A] { def apply(a: A) = f(a) }
}
case class Foo(i: Int, s: String)
sealed trait Root
case class Bar(i: Int) extends Root
case class Baz(s: String) extends Root
object Base {
implicit val stringWeight: Weight[String] = Weight(_.size)
implicit def intWeight: Weight[Int] = Weight(identity)
}
object ProductTC {
object WeightHelper extends ProductTypeClassCompanion[Weight] {
object typeClass extends ProductTypeClass[Weight] {
def emptyProduct: Weight[HNil] = Weight(_ => 0)
def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
Weight { case (h :: t) => hw(h) + tw(t) }
def project[F, G](w: => Weight[G], to: F => G,from: G => F): Weight[F] =
Weight(f => w(to(f)))
}
}
import Base._
import WeightHelper._
implicitly[Weight[Foo]]
implicitly[Weight[Bar]]
implicitly[Weight[Baz]]
illTyped("implicitly[Weight[Root]]")
}
object TC {
object WeightTypeClass extends TypeClassCompanion[Weight] {
object typeClass extends TypeClass[Weight] {
def emptyProduct: Weight[HNil] = Weight(_ => 0)
def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
Weight { case (h :: t) => hw(h) + tw(t) }
def project[F, G](w: => Weight[G], to: F => G, from: G => F): Weight[F] =
Weight(f => w(to(f)))
def emptyCoproduct: Weight[CNil] = Weight(_ => 0)
def coproduct[L, R <: Coproduct]
(lw: => Weight[L], rw: => Weight[R]): Weight[L :+: R] = Weight {
case Inl(h) => lw(h)
case Inr(t) => rw(t)
}
}
}
import Base._
import WeightTypeClass._
implicitly[Weight[Root]]
}

Scala - Confused with lazy syntax

Hello I'm reading the book called "Functional Programming in Scala". Book had code like this
trait Stream[+A] {
def uncons: Option[(A, Stream[A])]
def isEmpty: Boolean = uncons.isEmpty
}
object Stream {
...
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] =
new Stream[A] {
lazy val uncons = Some((hd, tl))
}
...
it says that hd: => A syntax is making this a lazy val
But the code in the github repo had something like this
trait Stream[+A]{
def toList: List[A] = {
#annotation.tailrec
def go(s: Stream[A], acc: List[A]) : List[A] = s match {
case Cons(h,t) => go(t(), h() :: acc)
case _ => acc
}
go(this, List()).reverse
}
}
case class Cons[+A](h: ()=>A, t: () => Stream[A]) extends Stream[A]
What is the difference between h: =>A and h: ()=>A.
Why is the second part of code has () after argument like go(t(), h(), :: acc)