4

I am using the State-Monad from the cats library to take care of the state of a card game I am implementing in Scala.

I have a function simulateGame which should end as soon as the status of a the current state is Over. The function looks like this.

def simulateGame: GameState[Outcome] = for {
    action <- State.inspect[PlayerState, Action] { ... }
    status <- step(action)
    outcome <- ???
} yield outcome

The step function returns the status after the current step. Depending on the returned status I want to either extract the outcome from the status (this is no problem since the outcome is encoded if the status is Over) or do a recursive call to the simulateGame function.

I am not sure how to pattern match on the status and then do the recursive call.

Any help is appreciated!

Lando-L
  • 843
  • 6
  • 19

1 Answers1

2

You can just match and recurse

def simulateGame: GameState[Outcome] = for {
    action <- State.inspect[PlayerState, Action] { ... }
    status <- step(action)
    outcome <- status match
       case o: Over => State.pure(o)
       case _ => simulateGame
} yield outcome
emilianogc
  • 880
  • 4
  • 19
  • Looks promising! I'll try that. I hope cats' State implementation safes me from running in a stackoverflow. – Lando-L Sep 11 '18 at 13:05
  • How would he flow the current state between recursive iterations? This will just produce a new state each time. – Yuval Itzchakov Sep 11 '18 at 16:54
  • @Lando-L It does, since it uses Eval for trampolined execution. – emilianogc Sep 11 '18 at 18:19
  • 1
    @YuvalItzchakov The game state "travels" inside the State monad, so the next simulateGame call will use the state left from the previous iteration. – emilianogc Sep 11 '18 at 18:24
  • @emilianogc Sorry, but what do you mean "travels inside"? State is immutable, it will produce the new state once you update it, it doesn't mutate itself. Once you recursively call the method and each call creates it's own state, you'll habey separate state at each stack frame. – Yuval Itzchakov Sep 11 '18 at 19:19
  • 1
    @YuvalItzchakov If the step function modifies the state inside the monad, then that state will be passed to the recursive simulateGame. – emilianogc Sep 12 '18 at 12:36
  • @emilianogc How? who passes it down to the next recursive call? What does "modifies the state state inside the monad? State *is* the monad, and it will produce a new copy on write. – Yuval Itzchakov Sep 12 '18 at 13:17
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/179914/discussion-between-emilianogc-and-yuval-itzchakov). – emilianogc Sep 12 '18 at 13:56