这是一个人工登录过程的基本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 ...'
}
1条答案
按热度按时间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)
这些行中的种类不正确
您的代码似乎是Scala 3。
我换了
与
例如,将type lambda
[A] =>> State[LoginProcessAlgebra[?], A]
转换为existential typeLoginProcessAlgebra[?]
Polymorphic method works with type lambda, but not with type wildcard in Scala 3
我还更换了
与
(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
。它不能被推断。代码现在已编译
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中我无法编译
https://scastie.scala-lang.org/DmytroMitin/Ov3BYdS5RjGXcXKEleoIlw/2
或
(this应该是Scala 3
type LoginProcessState = State[LoginProcessAlgebra[?], *]
的直译)https://scastie.scala-lang.org/DmytroMitin/Ov3BYdS5RjGXcXKEleoIlw/3
WeakTypeTag for higher kinded type
"can't existentially abstract over parameterized type..."