【问题标题】:Scala: Bad inferred type for Option composed with StateT monad transformerScala:使用 StateT monad 转换器组成的 Option 的错误推断类型
【发布时间】:2013-04-28 22:39:13
【问题描述】:

我对 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

到这个 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] monadic 值被推断为具有StateT[Id, String, String] 类型而不是StateT[Option, String, String]。为什么?

我正在使用 Scala 2.10.1、scalaz 7.0.0。

【问题讨论】:

    标签: scala haskell monads scalaz monad-transformers


    【解决方案1】:

    在您的示例中,对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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-31
      • 1970-01-01
      相关资源
      最近更新 更多