Aloha! :)
I'm not happy about running all the time to the stackoverflow forums to get some help with another piece of strangeness scala/cats has thrown at me. Problem is: There seems to be no really useful documentation, only some worthless - at least for me - repl lines.
Could please somebody of you point to some useful documentation? Some real code? Not just lines in the repl?
Here I just tried to work with scala/cats Eq and Show typeclasses... What the hell am I doing wrong?
The class:
package org.hudelundpfusch.utilites.decisions.data
import cats.Show
import cats.kernel.Eq
case class Fact[+T <: Any](name: String, value: T)
extends Equals {
override def canEqual(that: Any): Boolean = that match {
case _: Fact[_] => true
case _ => false
}
override def equals(other: Any): Boolean = other match {
case that: Fact[_] =>
(that canEqual this) &&
name == that.name &&
value == that.value
case _ => false
}
override def hashCode(): Int = {
val state = Seq(name, value)
state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
}
override def toString = s"Fact(name=$name, value=$value)"
}
case object Fact {
implicit val factEq: Eq[Fact[_]] = Eq.fromUniversalEquals[Fact[_]] // Neither of this works
// implicit def factEq: Eq[Fact[_]] = new Eq[Fact[_]] {
// def eqv(x: Fact[_], y: Fact[_]): Boolean = (x != null, y != null) match {
// case (true, _) => x.equals(y)
// case (_, true) => y.equals(x)
// case _ => true
// }
// }
implicit def factShow[T]: Show[Fact[T]] = (t: Fact[T]) => t.toString // Example calls for 'implicit val factShow[Fact[_]]' but that doesn't work
}
And the big surprise:
package org.hudelundpfusch.utilites.decisions
import cats._
import cats.data._
import cats.syntax._
import cats.implicits._
import cats.implicits.eq
import com.typesafe.scalalogging.LazyLogging
import org.hudelundpfusch.utilites.decisions.data.Fact
import org.hudelundpfusch.utilites.decisions.data.Fact._
// Tried to import everything that came to my mind to make the stuff working
object Fuddel
extends App
with LazyLogging {
logger.info("Let's start to fuddel!")
this.fuddel()
logger.info("Enough with fuddling!")
def fuddel(): Unit = {
val fact1: Fact[String] = Fact[String]("FactName", "FactValue")
println(s"${fact1.show}")
val fact2: Fact[String] = Fact[String]("FactName", "FactValue")
println(s"${fact2.show}")
println(s"${fact1.equals(fact2)}")
println(s"${fact1 == fact2}")
// println(s"${fact1 === fact2}") // Not resolved...According to the repl example this should work with implicits imported
println(s"${fact1 eq fact2}") // False? Oh joy! Thanks to the great repl example!
}
}
So please, is there any documentation not beeing worthless?
Thanks in advance
Have a better day than me
Alex
1. This here compiles just fine (I removed your package name and logging dependency):
import cats.Show
import cats.kernel.Eq
case class Fact[+T](name: String, value: T) extends Equals {
override def canEqual(that: Any): Boolean = that match {
case _: Fact[_] => true
case _ => false
}
override def equals(other: Any): Boolean = other match {
case that: Fact[_] => true // TODO: replaced, irrelevant
case _ => false
}
override def hashCode(): Int = {
val state = Seq(name, value)
state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
}
override def toString = s"Fact(name=$name, value=$value)"
}
case object Fact {
implicit def factEq[A]: Eq[Fact[A]] = Eq.fromUniversalEquals[Fact[A]]
implicit def factShow[T]: Show[Fact[T]] = (t: Fact[T]) => t.toString
}
Note the universal quantification instead of wildcard in factEq[A]
. Then in Fuddel.scala
:
import cats.syntax.show._
import cats.syntax.eq._
import Fact._
object Fuddel
extends App {
this.fuddel()
def fuddel(): Unit = {
val fact1: Fact[String] = Fact[String]("FactName", "FactValue")
println(s"${fact1.show}")
val fact2: Fact[String] = Fact[String]("FactName", "FactValue")
println(s"${fact2.show}")
println(s"${fact1.equals(fact2)}")
println(s"${fact1 == fact2}")
println(s"${fact1 === fact2}")
println(s"${fact1 eq fact2}")// must be false, different instances
}
}
Note that the eq
is a method that is available on every object in Scala, there is no way to override it.
2. I'd recommend to read Welsh, Gurnell "Scala with Cats". Scaladoc is good too, but you cannot navigate it effectively until you read the introductory chapter about the organization of packages and implicits in the cats
library.