简体   繁体   English

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

[英]Scala: Bad inferred type for Option composed with StateT monad transformer

I'm somewhat familiar with Haskell monad transformers, but new to Scalaz (version 7). 我对Haskell monad变换器有点熟悉,但对Scalaz(版本7)不熟悉。 I made (what I thought was) a straightforward translation from the following Haskell code: 我从以下Haskell代码中做了(我认为是)一个简单的翻译:

import Control.Monad.State

type Pass a = StateT String Maybe a

monadTest :: Pass String
monadTest = do
    s <- get
    return s

to this Scala code: 这个Scala代码:

import scalaz._
import Scalaz._

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

  def monadTest: Pass[String] =
    for {
      s <- get[String]
    } yield s
}

The Haskell code compiles. Haskell代码编译。 The Scala fails to compile, with the following error: 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]         ^

First, it seems scalaz implements StateT in terms of IndexedStateT . 首先,它似乎scalaz实现StateT来讲IndexedStateT Ok. 好。 But, it seems that the get[String] monadic value is inferred to have type StateT[Id, String, String] instead of StateT[Option, String, String] . 但是,似乎get[String] StateT[Id, String, String]值被推断为具有类型StateT[Id, String, String]而不是StateT[Option, String, String] Why? 为什么?

I'm using Scala 2.10.1, scalaz 7.0.0. 我正在使用Scala 2.10.1,scalaz 7.0.0。

In your example, the call to get[String] is calling the get method of StateFunctions , reproduced here: 在您的示例中,对get[String]的调用是调用StateFunctionsget方法,在此处再现:

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

Where State[S, A] is an alias for StateT[Id, S, A] which is an alias for IndexedStateT[Id, S, S, A] . 其中State[S, A]StateT[Id, S, A]的别名,它是IndexedStateT[Id, S, S, A]的别名。

Because you are using StateT , you need to call get on an instance of StateTMonadState[S, F] , or StateTMonadState[String, Option] in your case. 由于您使用StateT ,你需要调用get对一个实例StateTMonadState[S, F]StateTMonadState[String, Option]你的情况。 The working example is: 工作示例是:

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
}

The MonadState instance can also be resolved implicitly via MonadState[F[_, _], S] but it is less convenient to use due to the type lambda required. MonadState实例也可以通过MonadState[F[_, _], S]隐式解析MonadState[F[_, _], S]但由于需要lambda类型,因此使用起来不太方便。 See MonadState.scala and StateT.scala for more info. 有关详细信息,请参阅MonadState.scala和StateT.scala。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM