Scala Tagless Final - 不编译

问题描述 投票:0回答:1

这是人为登录过程的基本 Scala Tagless Final 模式实现。它不会编译,因为它在结尾附近显示“没有找到参数的隐式......”

但是,如果我从程序泛型类型中删除

': Monad: LoginProcessAlgebra[F]'
,特定错误就会消失,但理解开始抱怨,因为
F[_]
不再缩小到 Monad

问题: 为什么 Scala 认为 State 不是 Monad?

import cats.Monad
import cats.data.State
import cats.implicits._

import java.util.UUID
import scala.language.higherKinds

case class Credentials(uid: String, pwd: String)
case class Session(sessionId: String, credentials: Credentials)

object LoginProcessTaglessFinal {

  trait LoginProcessAlgebra[F[_]] {
    def captureCredentials(name: String, password: String): F[Credentials]
    def login(credentials: Credentials): F[Session]
  }

  type LoginProcessState = State[LoginProcessAlgebra[_], _]
  type LoginProcessStateA[A] = LoginProcessState[A]

  implicit object LoginProcessInterpreterUsingState extends LoginProcessAlgebra[LoginProcessStateA] {
    override def captureCredentials(name: String, password: String): LoginProcessStateA[Credentials] =
      State(login => (login, Credentials(name, password)))
    override def login(credentials: Credentials): LoginProcessStateA[Session] =
      State(login => (login, Session(UUID.randomUUID().toString, credentials)))
  }

  def program[F[_]: Monad: LoginProcessAlgebra[F]](userName: String, password: String)
    (implicit interpreter: LoginProcessAlgebra[F]): F[Session] = for {
      credentials <-  interpreter.captureCredentials(userName, password)
      session <-  interpreter.login(credentials)
    } yield session


  val sessionState = program("someUserName", "p455w0rd")
  //compile error here 
  //due to 'No implicits found for parameters ...'
}
scala functional-programming scala-cats tagless-final
1个回答
1
投票

import scala.language.higherKinds
已弃用。没有必要。

编译错误更早开始

https://scastie.scala-lang.org/DmytroMitin/cVmdwXy7RKSWUbn9V0TBGw(Scala 2)

https://scastie.scala-lang.org/DmytroMitin/cVmdwXy7RKSWUbn9V0TBGw/6(Scala 3)

你在这些行中的种类不正确

type LoginProcessState = State[LoginProcessAlgebra[_], _]
type LoginProcessStateA[A] = LoginProcessState[A]

这似乎是 Scala 3.

我换了

type LoginProcessState = State[LoginProcessAlgebra[_], _]

// scalacOptions += "-Ykind-projector"

type LoginProcessState = State[LoginProcessAlgebra[?], *]

(即 类型 lambda

[A] =>> State[LoginProcessAlgebra[?], A]
存在类型
LoginProcessAlgebra[?]
,另见 Polymorphic method works with type lambda, but not with type wildcard in Scala 3)。

我也换了

def program[F[_]: Monad: LoginProcessAlgebra[F]](userName: String, password: String)
    (implicit interpreter: LoginProcessAlgebra[F]): F[Session]

def program[F[_]: Monad](userName: String, password: String)
    (implicit interpreter: LoginProcessAlgebra[F]): F[Session]

LoginProcessAlgebra
可以是上下文绑定,而不是
LoginProcessAlgebra[F]
;你也有上下文绑定和相同的隐式再次,这是不正确的)。

现在错误是

Ambiguous given instances: both value catsStdInstancesForOption in trait OptionInstances and value catsStdInstancesForVector in trait VectorInstances match type cats.Monad[F] of an implicit parameter of method program in object LoginProcessTaglessFinal

https://scastie.scala-lang.org/DmytroMitin/cVmdwXy7RKSWUbn9V0TBGw/3

你只需要指定类型参数

LoginProcessStateA
。无法推断。

val sessionState = program[LoginProcessStateA]("someUserName", "p455w0rd")

https://scastie.scala-lang.org/DmytroMitin/cVmdwXy7RKSWUbn9V0TBGw/5

LoginProcessStateA
好像和
LoginProcessState
一样。我正在删除前者。

https://scastie.scala-lang.org/DmytroMitin/cVmdwXy7RKSWUbn9V0TBGw/13

© www.soinside.com 2019 - 2024. All rights reserved.