找不到参数半群的隐含值

时间:2018-02-24 21:32:20

标签: scala scala-cats

我刚刚尝试编译以下代码:

import cats.Monoid
import cats.instances.boolean._ // for Monoid
import cats.instances.int._ // for Monoid
import cats.instances.list._ // for Monoid
import cats.instances.string._ // for Monoid
import cats.syntax.apply._ // for imapN
import cats.syntax.semigroup._

case class Cat2(name: String, yearOfBirth: Int, favoriteFoods: List[String])

object FancyFunctor {

  val tupleToCat: (String, Int, List[String]) => Cat2 =
    Cat2.apply _

  val catToTuple: Cat2 => (String, Int, List[String]) =
    cat => (cat.name, cat.yearOfBirth, cat.favoriteFoods)

  implicit val catMonoid: Monoid[Cat2] = (
    Monoid[String],
    Monoid[Int],
    Monoid[List[String]]
  ).imapN(tupleToCat)(catToTuple)

  def main(args: Array[String]): Unit = {

    val garfield = Cat2("Garfield", 1978, List("Lasagne"))
    val heathcliff = Cat2("Heathcliff", 1988, List("Junk Food"))

    val a = garfield |+| heathcliff

  }

}

我收到了错误消息:

[info] Compiling 1 Scala source to /home/developer/Desktop/scala/catssemigroupal/target/scala-2.12/classes ...
[error] /home/developer/Desktop/scala/catssemigroupal/src/main/scala/io/khinkali/FancyFunctor.scala:25:22: could not find implicit value for parameter semigroupal: cats.Semigroupal[cats.kernel.Monoid]
[error]   ).imapN(tupleToCat)(catToTuple)
[error]                      ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 1 s, completed Feb 24, 2018, 10:18:01 PM

我做错了什么?

2 个答案:

答案 0 :(得分:3)

这与猫1.0.1编译:

import cats.Monoid
import cats.instances.boolean._ // for Monoid
import cats.instances.int._ // for Monoid
import cats.instances.list._ // for Monoid
import cats.instances.string._ // for Monoid
import cats.syntax.apply._ // for imapN
import cats.syntax.semigroup._ // for |+|
import cats.instances.invariant._ // for  catsSemigroupalForMonoid: InvariantSemigroupal[Monoid] 

object FancyFunctor {

  /*
  val tupleToCat: (String, Int, List[String]) => Cat2 =
    Cat2.apply _

  val catToTuple: Cat2 => (String, Int, List[String]) =
    cat => (cat.name, cat.yearOfBirth, cat.favoriteFoods)

  */

  case class Cat2(name: String, yearOfBirth: Int, favoriteFoods: List[String])
  implicit val catMonoid: Monoid[Cat2] = (
    Monoid[String],
    Monoid[Int],
    Monoid[List[String]]
  ).imapN(Cat2.apply)(c => Cat2.unapply(c).get)

  def main(args: Array[String]): Unit = {

    val garfield = Cat2("Garfield", 1978, List("Lasagne"))
    val heathcliff = Cat2("Heathcliff", 1988, List("Junk Food"))

    val a = garfield |+| heathcliff

  }

}

如何快速找到除浏览器之外的任何东西(没有IDE):

  • Doc
  • 中搜索Semigroupal(缺少类型类别)
  • 使用结果页面上的浏览器的文本搜索搜索Monoid
  • 点击返回Semigroupal[Monoid]
  • 的隐式方法
  • 点击定义课程的链接:InvariantMonoidalInstances
  • 寻找线性子类,选择比#34; all"
  • 更精确的东西

提示:过度杀伤方法cats.implicits._适用于您的代码。

作为奖励:您不必重新定义Cat2.applyCat2.unapply,它们会自动为每个case级提供。

答案 1 :(得分:1)

在阅读本书时,我也对此问题感到有点困惑(这是一本很棒的书!)。有两件事使我意识到,我需要来自import cats.instances.invariant._的Invariant类型类:

1)代码上方的文本为

  

例如,我们可以使用不变式来组合Monoids

但是在范围上没有可见的不变性!

2)如果单击imapN方法,您将看到它采用了两个隐式参数implicit invariant: Invariant[F], semigroupal: Semigroupal[F]

这两件事结合在一起,使您寻找一种在范围内添加不变式的方法。而且由于整本书中,这样做的普遍方法是从cats.instances...中获得它们,这就是我所做的。希望有道理。