Как написать для понимания у кошек с монадой IO - PullRequest
5 голосов
/ 01 июля 2019

У меня есть следующий код:

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.Есть ли более умный способ сделать это?Может быть, мне стоит как-то отделить задачи от основного алгоритма, т.е. от этого для понимания?Или я должен сделать это так?

...