Reputation: 38
Aloha! :)
Could please somebody point me to a useful scala/cats tutorial? I’m struggling with making a class a functor for the last few days and I’m about to punch a hole in my display. All the documentation I’ve found up until now was not of help for me.
Maybe I should give Eta a try... =D
Here is the class I would like to turn into a functor. Besides 'show' doesn't behave the way I expected also.
package org.hudelundpfusch.utilites.decisions.data
import cats.{Functor, Show}
import cats.kernel.Eq
import cats.syntax.functor._
import cats.syntax.show._
import scala.reflect.runtime.universe
import scala.reflect.runtime.universe._
case class Fact[T <: Any] (name: String, value: T) (implicit private val paramTypeTagT: WeakTypeTag[T])
extends Equals {
val paramType: universe.Type = paramTypeTagT.tpe
val paramTypeClass: Option[Class[_ <: T]] = if (value != null) {
Some(value.getClass)
} else {
None
}
def map[A, B](fa: Fact[A])(f: A => B): Fact[B] = Fact[B](fa.name, f(fa.value))
override def canEqual(other: Any): Boolean = other.isInstanceOf[Fact[_]]
override def equals(other: Any): Boolean = other match {
case that: Fact[_] =>
(that canEqual this) &&
name == that.name
paramType == that.paramType &&
paramTypeClass == that.paramTypeClass &&
value == that.value
case _ => false
}
override def hashCode(): Int = {
val state = Seq(name, paramType, paramTypeClass, value)
state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
}
override def toString = s"Fact(name=${name}, paramType=$paramType, paramTypeClass=$paramTypeClass, value=$value)"
}
case object Fact extends Show[Fact[_]] {
override def show(t: Fact[_]): String = t.toString
}
Thanks in advance
Have a nice day
Alex
Update:
package org.hudelundpfusch.utilites.decisions.data
import cats.{Functor, Show}
import cats.kernel.Eq
import cats.syntax.functor._
import cats.syntax.show._
import scala.reflect.runtime.universe
import scala.reflect.runtime.universe._
case class Fact[T <: Any] (name: String, value: T) (implicit private val paramTypeTagT: WeakTypeTag[T])
extends Functor[Fact]
with Equals {
val paramType: universe.Type = paramTypeTagT.tpe
val paramTypeClass: Option[Class[_ <: T]] = if (value != null) {
Some(value.getClass)
} else {
None
}
def map[A, B](fa: Fact[A])(f: A => B): Fact[B] = Fact[B](fa.name, f(fa.value))
override def canEqual(other: Any): Boolean = other.isInstanceOf[Fact[_]]
override def equals(other: Any): Boolean = other match {
case that: Fact[_] =>
(that canEqual this) &&
name == that.name
paramType == that.paramType &&
paramTypeClass == that.paramTypeClass &&
value == that.value
case _ => false
}
override def hashCode(): Int = {
val state = Seq(name, paramType, paramTypeClass, value)
state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
}
override def toString = s"Fact(name=${name}, paramType=$paramType, paramTypeClass=$paramTypeClass, value=$value)"
}
Okay, I tried this now:
object Fact {
implicit val factFunctor: Functor[Fact] = new Functor[Fact] {
override def map[A, B](fa: Fact[A])(f: A => B): Fact[B] = Fact[B](fa.name, f(fa.value))
}
implicit def factShow[T]: Show[Fact[T]] = new Show[Fact[T]] {
override def show(t: Fact[T]): String = this.toString
}
}
Unfortunately the call to the mapping function looks a bit cumbersome:
package org.hudelundpfusch.utilites.decisions.data
object Fuddel {
def main(args: Array[String]): Unit = {
val fact1: Fact[Int] = Fact("Fact-1", 23)
val fact2 = Fact.factFunctor.map(fact1){x: Int => x * 2}
println(s"$fact2")
}
}
Upvotes: 0
Views: 699
Reputation: 51658
With Cats you do not extend Show, Functor traits (OOP way), you create implicit instances of Show, Functor (FP way).
http://eed3si9n.com/herding-cats/Functor.html
https://typelevel.org/cats/typeclasses/functor.html
implicit def factShow[T]: Show[Fact[T]] = new Show[Fact[T]] {
override def show(t: Fact[T]): String = ???
}
// implicit object factFunctor extends Functor[Fact] {
// override def map[A, B](fa: Fact[A])(f: A => B): Fact[B] = ???
// }
implicit val factFunctor: Functor[Fact] = new Functor[Fact] {
override def map[A, B](fa: Fact[A])(f: A => B): Fact[B] = ???
}
Show[Fact[Int]].show(Fact("a", 1))
Functor[Fact].map(Fact("a", 1))(_ + 1)
import cats.syntax.show._
Fact("a", 1).show
import cats.syntax.functor._
Fact("a", 1).map(_ + 1)
Just in case, Fact[_]
in your case object Fact extends Show[Fact[_]]
is existential type, and Fact
in my implicit object factFunctor extends Functor[Fact]
is higher-kinded type.
Upvotes: 6