Scala:使用StateT monad转换器组成的选项的错误推断类型

ala*_*ode 5 monads haskell scala monad-transformers scalaz

我对Haskell monad变换器有点熟悉,但对Scalaz(版本7)不熟悉.我从以下Haskell代码中做了(我认为是)一个简单的翻译:

import Control.Monad.State

type Pass a = StateT String Maybe a

monadTest :: Pass String
monadTest = do
    s <- get
    return s
Run Code Online (Sandbox Code Playgroud)

这个Scala代码:

import scalaz._
import Scalaz._

object StateTest {
  type Pass[A] = StateT[Option, String, A]

  def monadTest: Pass[String] =
    for {
      s <- get[String]
    } yield s
}
Run Code Online (Sandbox Code Playgroud)

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]         ^
Run Code Online (Sandbox Code Playgroud)

首先,似乎scalaz实现StateTIndexedStateT.好.但是,似乎get[String]推断monadic值具有类型StateT[Id, String, String]而不是StateT[Option, String, String].为什么?

我正在使用Scala 2.10.1,scalaz 7.0.0.

mpi*_*ist 8

在您的示例中,get[String]调用get方法是调用StateFunctions此处的方法:

def get[S]: State[S, S] = init
Run Code Online (Sandbox Code Playgroud)

State[S, A]别名在哪里是StateT[Id, S, A]别名IndexedStateT[Id, S, S, A].

因为您正在使用StateT,所以您需要调用get实例StateTMonadState[S, F],或者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
}
Run Code Online (Sandbox Code Playgroud)

MonadState实例还可以通过隐含解决MonadState[F[_, _], S],但它是使用不太方便,因为需要的类型拉姆达.有关详细信息,请参阅MonadState.scala和StateT.scala.