如何在scala / cats中使用函子

Ale*_*ell 0 scala scala-cats

阿罗哈!:)

能否请别人指出我一个有用的scala / cats教程?最近几天,我一直在努力使课程成为函子,我将在显示器上打一个洞。到目前为止,我找到的所有文档对我都没有帮助。

也许我应该试试Eta ... = D

这是我想变成函子的课程。除了“表演”外,我的行为也不像我预期的那样。

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

}
Run Code Online (Sandbox Code Playgroud)

提前致谢

祝你今天愉快

亚历克斯

更新:

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)"

}
Run Code Online (Sandbox Code Playgroud)

好吧,我现在尝试了这个:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,对映射函数的调用看起来有点麻烦:

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")
  }
}
Run Code Online (Sandbox Code Playgroud)

Dmy*_*tin 6

使用Cats时,您不扩展Show,Functor特性(OOP方法),而是创建Show,Functor(FP方法)的隐式实例。

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)
Run Code Online (Sandbox Code Playgroud)

以防万一,Fact[_]在你case object Fact extends Show[Fact[_]]是存在型的,而Fact在我implicit object factFunctor extends Functor[Fact]是更高种的类型。

  • 在此处投放广告有两件事。1.不要使用“隐式对象”,它们有时会破坏隐式分辨率,请始终使用带有显式_type_签名的“隐式值”(“隐式值factFuntor:Functor [Fact] = new Functor [Fact] { ...}`)。-2.澄清一下,这不是猫的事,这是_typeclass_模式的本质。您的班级不再是F。但是,它确实有一个F的实例。诀窍是_is a_与_has a_的区别。 (2认同)
  • @AlexanderSchell如前所述:您缺少`import cats.syntax.functor._`。导入后,您应该可以编写`fact1.map(_ * 2)`。 (2认同)
  • @AlexanderSchell呵呵,什么?否。请,如果这解决了您的问题,只需将*答案*标记为可接受的*答案*。如果您认为应将评论部分中的内容复制到答案中,请告诉我们,我们可以进行任何编辑。或建议您自己进行编辑(我不知道,也许这在特定阈值以下行不通)。 (2认同)