【发布时间】:2019-11-11 16:49:37
【问题描述】:
我有以下代码:
import cats.effect.IO
import cats.data.State
import cats.data.StateT
import cats.implicits._
import cats.effect.LiftIO
abstract class Example {
object implicits {
implicit def myEffectLiftIO: LiftIO[IOGameplay] =
new LiftIO[IOGameplay] {
override def liftIO[A](ioa: IO[A]): IOGameplay[A] = {
StateT.liftF(ioa)
}
}
}
type Gameplay[A] = State[GameState, A]
type IOGameplay[A] = StateT[IO, GameState, A]
type EitherDirection[A] = Either[Throwable, A]
type Map = Array[Array[FieldType]]
sealed trait FieldType
case class GameState(map: Map, block: Block)
case class Block(f1: Field, f2: Field)
case class Field()
import implicits._
val L = implicitly[LiftIO[IOGameplay]]
sealed trait GameResult
sealed trait Direction
trait IOMonad {
def println(msg: String): IO[Unit]
def readln(): IO[String]
}
def play(io: IOMonad): StateT[IO, GameState, GameResult] = {
val L = implicitly[LiftIO[IOGameplay]]
for {
// print map to the console
_ <- L.liftIO(io.println("Next move: "))
directionOpt <- L.liftIO(readDirection(io))
direction <- StateT.liftF[IO, GameState, Direction](IO.fromEither(directionOpt))
nextBlock <- IO(nextBlock(direction))
gameResult <- calculate(nextBlock)
} yield {
gameResult
}
}
def readDirection(io: IOMonad): IO[EitherDirection[Direction]]
def nextBlock(direction: Direction): Gameplay[Block]
def calculate(block: Block): Gameplay[GameResult]
}
这并不完全准确,但我发布了整个块来解释问题。
在这里,我对值进行了许多转换以产生 IO 并将其转换为 StateT。有没有更聪明的方法来做到这一点?也许我应该以某种方式将 io 任务与主算法分开,即与这个理解分开?还是我应该这样做?
【问题讨论】:
-
如果你发布一个完整的例子会更容易帮助你。我建议不要从您的实际代码中发布 sn-p(留出很大的解释空间,例如
L),而是建议创建一个可以成功编译的小示例程序(例如在 scalafiddle 中)。 -
@MarkusAppel 我发布了整个代码。由于play方法中的理解,它不会编译,这实际上是我的问题的主题。如果您能就任何其他可以改进的事情给我建议,我将非常感激。
-
看起来好多了,现在人们可以更轻松地找出问题所在。感谢您听取建议。 :)
标签: scala scala-cats cats-effect