Pregunta Scala: tipo inferido incorrecto para la opción compuesta con transformador de mónada StateT


Estoy algo familiarizado con los transformadores de mónada Haskell, pero nuevo en Scalaz (versión 7). Hice (lo que pensé que era) una traducción directa del siguiente código de Haskell:

import Control.Monad.State

type Pass a = StateT String Maybe a

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

a este código Scala:

import scalaz._
import Scalaz._

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

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

El código de Haskell se compila. El Scala no se compila, con el siguiente error:

[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]         ^

Primero, parece que Scalaz implementa StateT en términos de IndexedStateT. De acuerdo. Pero, parece que el get[String] Se infiere que el valor monádico tiene tipo StateT[Id, String, String] en lugar de StateT[Option, String, String]. ¿Por qué?

Estoy usando Scala 2.10.1, scalaz 7.0.0.


5
2018-04-28 22:39


origen


Respuestas:


En tu ejemplo, la llamada a get[String] está llamando al get método de StateFunctions, reproducido aquí:

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

Dónde State[S, A] es un alias para StateT[Id, S, A] que es un alias para IndexedStateT[Id, S, S, A].

Porque estás usando StateT, necesitas llamar get en una instancia de StateTMonadState[S, F], o StateTMonadState[String, Option] en tu caso. El ejemplo de trabajo es:

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
}

los MonadState instancia también se puede resolver implícitamente a través de MonadState[F[_, _], S] pero es menos conveniente de usar debido al tipo lambda requerido. Vea MonadState.scala y StateT.scala para más información.


8
2018-04-28 23:27