Scala无标记Final -未编译

ldioqlga  于 2023-03-08  发布在  Scala
关注(0)|答案(1)|浏览(146)

这是一个人工登录过程的基本Scala无标记Final模式实现。它没有编译,因为它在结尾处显示“No implicit found for parameters...”
但是,如果我从程序泛型类型中删除': Monad: LoginProcessAlgebra[F]',则该特定错误会消失,但是for-理解开始抱怨,因为F[_]不再被缩小为Monad
问:为什么Scala认为State不是单子?

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 ...'
}
4sup72z8

4sup72z81#

import scala.language.higherKinds已弃用(自Scala 2.13.1起)。
编译错误提前开始
https://scastie.scala-lang.org/DmytroMitin/cVmdwXy7RKSWUbn9V0TBGw(可扩展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[?], *]

例如,将type lambda[A] =>> State[LoginProcessAlgebra[?], A]转换为existential typeLoginProcessAlgebra[?]
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]

(it的LoginProcessAlgebra可以是上下文绑定,而不是LoginProcessAlgebra[F];同样,您也有上下文绑定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
你只需要在调用点指定类型参数F=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
同样在Scala 3中,最好使用given/using而不是implicit
https://scastie.scala-lang.org/DmytroMitin/cVmdwXy7RKSWUbn9V0TBGw/16
在Scala 2中我无法编译

type LoginProcessState[A] = State[LoginProcessAlgebra[F], A] forSome { type F[_] }

https://scastie.scala-lang.org/DmytroMitin/Ov3BYdS5RjGXcXKEleoIlw/2

scalac: 
  ?BoundedWildcardType?
     while compiling: ...
        during phase: typer

  last tree to typer: Apply(method apply)
       tree position: ...
            tree tpe: Credentials
              symbol: case method apply in object Credentials
   symbol definition: case def apply(uid: String, pwd: String): Credentials (a MethodSymbol)
      symbol package: <empty>
       symbol owners: method apply -> object Credentials -> object App
           call site: method captureCredentials in object LoginProcessInterpreterUsingState in package <empty>

type LoginProcessAlgebraE = LoginProcessAlgebra[F] forSome { type F[_] }
type LoginProcessState[A] = State[LoginProcessAlgebraE, A]

(this应该是Scala 3 type LoginProcessState = State[LoginProcessAlgebra[?], *]的直译)
https://scastie.scala-lang.org/DmytroMitin/Ov3BYdS5RjGXcXKEleoIlw/3

can't existentially abstract over parameterized type F
  State((login: LoginProcessAlgebraE) => (login, Credentials(name, password)))
  State((login: LoginProcessAlgebraE) => (login, Session(UUID.randomUUID().toString, credentials)))

WeakTypeTag for higher kinded type
"can't existentially abstract over parameterized type..."

相关问题