我正在研究一個遊戲原型,並試圖儘可能地純粹。 所有用例都放入一個場景 -來自ReaderWriterState的短路[任一]
- 試圖找到播放器在存儲
- 在存儲
- 執行一些業務邏輯
- 更新玩家在更新一個能產生一定的輸出 - 日誌消息,轉發到其他播放器等
從另一個側面一個已經拿到進入環境(數據庫,資源等),全球遊戲狀態(不可變的遊戲CONFIGS,種子等等)。
爲了配合它一起我結束了scalaz7 ReaderWriterState單子是這樣的:
一些定義:
trait UserService
trait Environment
trait State
sealed trait Error
sealed trait Output
case object GameEnvironment extends Environment
case object GameState extends State
object Output {
case object Log extends Output
case object Parcel extends Output
case object Analytics extends Output
}
object Error {
case class AppError(code: String) extends Error
case class ThrowableError(ex: Exception) extends Error
}
服務方法的返回類型 - 提供了通過讀卡器獲取環境,產生一些通過Writer輸出,可以訪問GameState併產生方法結果 - 錯誤或某種類型
type Result[T] = ReaderWriterState[Environment, List[Output], State, Error \/ T]
只是一個關於如何服務可能會實現
object UserServiceImpl extends UserService {
def findPlayer(id: Long): Result[Player] = ReaderWriterState { (env, state) =>
(
Nil,
\/-(Player(id, "name")),
state
)
}
def updatePlayer(player: Player): Result[Player] = ReaderWriterState { (env, state) =>
(
List(Output.Log),
\/-(player.copy(name = "updated")),
state
)
}
}
上面提到的場景的例子是(不會編譯):
val (out, res, state) = (for {
playerOrError <- userService.findPlayer(1L) //How to short-circuit if findPlayer returns left either?
updated <- userService.updatePlayer(playerOrError) //How to transform playerOrError to right projection and pass it here?
} yield player).run(GameEnvironment, GameState)
所以,我的問題是:
- 如何findPlayer:RWS返回左邊?
- 如何將playerOrError轉換爲正確的投影並將其傳遞給此處?
它看起來像我可以嘗試使用變壓器,但無法繞過它。
謝謝!
謝謝,我會嘗試。是'?'用特殊的編譯器插件替換類型lamda?我正在玩類型lambda和這項任務,但失敗 –
哦,是的,'?'來自[種類投影機](https://github.com/non/kind-projector/)。 –