簡體   English   中英

無法為具有語法擴展的類型F [A1,A2]的類型恢復類型類實例

[英]Unable to recover typeclass instances for types with kind F[A1, A2] with syntax extensions

我一直在使用Scala中的類型類模式來更好地理解它是如何工作的,因為我熟悉Scalaz並且想要弄清楚它是如何工作的“引擎蓋下”。

(您可以使用https://ammonite.io/ REPL運行以下代碼)

import $plugin.$ivy.`org.spire-math::kind-projector:0.9.3`

sealed trait Maybe[+A] // Option
final case class Just[+A](value: A) extends Maybe[A]
final case object Null extends Maybe[Nothing]

sealed trait Direction[+E, +A] // Either
final case class Up[+E, +A](value: A) extends Direction[E, A]
final case class Down[+E, +A](value: E) extends Direction[E, A]

trait Functor[F[_]] {
  def map[A, B](fa: F[A])(f: A => B): F[B]
}

object FunctorSyntax {
  implicit final class FunctorExtensions[F[_], A](private val self: F[A]) extends AnyVal {
    def map[B](f: A => B)(implicit instance: Functor[F]): F[B] = {
      instance.map(self)(f)
    }
  }
}

object FunctorInstances {
  implicit val maybeFunctorInstance: Functor[Maybe] = new Functor[Maybe] {
    def map[A, B](fa: Maybe[A])(f: A => B): Maybe[B] = fa match {
      case Just(a) => Just(f(a))
      case n@Null => n
    }
  }

  implicit def directionFunctorInstance[E]: Functor[Direction[E, ?]] = new Functor[Direction[E, ?]] {
    def map[A, B](fa: Direction[E, A])(f: A => B): Direction[E, B] = fa match {
      case Up(a) => Up(f(a))
      case Down(e) => Down(e)
    }
  }
}

所以,我已經寫了一些類似物OptionMaybe ),並EitherDirection ),該Functor定義,有些情況下Functor ,有的一些語法擴展,所以我可以叫.map上有效的函子。

以下代碼有效:

import FunctorInstances._
import FunctorSyntax._

val x: Maybe[Int] = Just(5)

println(x.map(_ + 1)) // prints "Just(6)"

正如所料。 但以下不是:

val y: Direction[String, Int] = Up(5)

println(y.map(_ + 1)) // errors out

拋出錯誤help.sc:48: value map is not a member of ammonite.$file.help.Direction[String,Int]

簡單地說,我不希望發生此錯誤,並且.map可以在任意Direction[E, ?] .map Direction[E, ?]

我認為Scala無法看到Direction[String, Int]可以被解構為F = Direction[String, ?] FunctorExtensions F = Direction[String, ?]A = String ,從而阻止FunctorExtensions類將自己包裹在val y: Direction[String, Int]周圍val y: Direction[String, Int] 不幸的是,我不知道如何解決這個問題。

注意:實例本身仍然可以implicitly恢復

val instance = implicitly[Functor[Direction[String, ?]]]
println(instance.map(y)(_ + 1)) // prints "Up(6)"

如果您使用的是Scala 2.11或Scala 2.12,則可能缺少-Ypartial-unification scalac選項。

scalacOptions += "-Ypartial-unification"到您的構建中,或者您可以使用默認情況下啟用它的Scala 2.13。

請參閱https://github.com/typelevel/cats/blob/v1.6.1/README.md#getting-started

這對我有用,具有以下設置:

Welcome to the Ammonite Repl 1.6.3
(Scala 2.12.8 Java 1.8.0_141)

添加interp設置似乎有效

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM