Scala: неверный предполагаемый тип для Option, созданного с помощью преобразователя монад StateT

Я немного знаком с преобразователями монад 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 реализует StateT с точки зрения IndexedStateT. В порядке. Но похоже, что монадическое значение get[String] имеет тип StateT[Id, String, String] вместо StateT[Option, String, String]. Почему?

Я использую Scala 2.10.1, scalaz 7.0.0.


person alanlcode    schedule 28.04.2013    source источник


Ответы (1)


В вашем примере вызов get[String] вызывает метод get StateFunctions, воспроизведенный здесь:

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

Где 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
}

Экземпляр MonadState также может быть разрешен неявно через MonadState[F[_, _], S], но его менее удобно использовать из-за требуемого типа лямбда. См. MonadState.scala и StateT.scala для получения дополнительной информации.

person mpilquist    schedule 28.04.2013