Scala:由 StateT 单元变压器组成的 Option 的不良推断类型



我对Haskell单体变压器有些熟悉,但对Scalaz(版本7(很陌生。 我从以下Haskell代码中做了一个简单的翻译(我认为是(:

import Control.Monad.State
type Pass a = StateT String Maybe a
monadTest :: Pass String
monadTest = do
    s <- get
    return s

到这个 Scala 代码:

import scalaz._
import Scalaz._
object StateTest {
  type Pass[A] = StateT[Option, String, A]
  def monadTest: Pass[String] =
    for {
      s <- get[String]
    } yield s
}

Haskell代码编译。 Scala 编译失败,并出现以下错误:

[error] .../StateTest.scala:9: type mismatch;
[error]  found   : scalaz.IndexedStateT[scalaz.Id.Id,String,String,String]
[error]  required: StateTest.Pass[String]
[error]     (which expands to)  scalaz.IndexedStateT[Option,String,String,String]
[error]       s <- get[String]
[error]         ^

首先,似乎 scalaz 在IndexedStateT方面实现了StateT。 还行。 但是,似乎get[String]一元值被推断为具有类型 StateT[Id, String, String] 而不是 StateT[Option, String, String] 。 为什么?

我正在使用 Scala 2.10.1、scalaz 7.0.0。

在您的示例中,对get[String]的调用正在调用 StateFunctionsget 方法,此处重现:

def get[S]: State[S, S] = init

其中State[S, A]StateT[Id, S, A]的别名,IndexedStateT[Id, S, S, A]的别名。

因为您使用的是 StateT ,所以您需要在 StateTMonadState[S, F] 的实例上调用 get,或者在您的情况下调用StateTMonadState[String, Option]。工作示例是:

import scalaz._
import Scalaz._
object StateTest {
  type Pass[A] = StateT[Option, String, A]
  val sm = StateT.stateTMonadState[String, Option]
  def monadTest: Pass[String] =
    for {
      s <- sm.get
    } yield s
}

MonadState实例也可以通过 MonadState[F[_, _], S] 隐式解析,但由于所需的 lambda 类型,使用起来不太方便。有关更多信息,请参阅 MonadState.scala 和 StateT.scala。

最新更新