在程序中将State monad结果从一个步骤传递到另一个步骤+尽早停止

时间:2019-06-12 16:12:51

标签: scala functional-programming monads scala-cats for-comprehension

我有以下步骤:

trait BlackjackSteps {
    def gamerTakesTwoCards(gamerName:String): State[Deck, Gamer]
    def dealerTakesTwoCards: State[Deck, Dealer]
    def isBlackjack(gamer: Gamer, dealer: Dealer): Option[Player]
    def gamerDrawsCards(gamer: Gamer): State[Deck, Gamer]
    def dealerDrawsCards(dealer: Dealer, gamer: Gamer): State[Deck, Dealer]
    def determineWinner(gamer: Gamer, dealer: Dealer): Player

    def program(gamerName:String): State[Deck, Player] = for {
      gamer <- gamerTakesTwoCards(gamerName)
      dealer <- dealerTakesTwoCards
      //winner = isBlackjack(gamer, dealer)
      gamerFinal <- gamerDrawsCards(gamer)
      dealerFinal <- dealerDrawsCards(dealer, gamerFinal)
      winnerFinal = determineWinner(gamerFinal, dealerFinal)
    } yield  winnerFinal
  }

两个问题:

  • 我如何获得gamerTakesTwoCards产生的Deck并将其传递给DealerTakesTwoCards?

  • isBlackjack可能会导致赢家,在这种情况下,我需要停止并返回赢家。如何更改上面的代码来做到这一点?

游戏:

  • 玩家和发牌人
  • 他们俩都抓了两张牌
  • 如果没有21名获胜者
  • 玩家保留抽奖牌直到17
  • 最高得分不超过21分的玩家获胜!

在此处填写代码:https://bitbucket.org/jameskingconsulting/blackjack-scala/src/master/

编辑:

我已经不再理解了,只是弄清楚发生了什么:

def program(gamerName:String): State[Deck, Player] =
      gamerTakesTwoCards(gamerName).flatMap( gamer =>
        dealerTakesTwoCards.flatMap(dealer =>
          isBlackjack(gamer, dealer).fold(

            gamerDrawsCards(gamer).flatMap( gamerFinal =>
              dealerDrawsCards(dealer, gamerFinal).map( dealerFinal =>
                determineWinner(gamerFinal, dealerFinal)
              )
            )

          )(State.pure[Deck, Player])
        ))

1 个答案:

答案 0 :(得分:2)

  1. 无事可做。这就是重点。
  2. 在两种情况下,您都必须归还获胜者 ,无论isBlackjack返回None还是Some都是如此。无论哪种方式,您都必须返回State[Deck, Player]。例如,您可以在fold上使用Option,通过pure映射成功案例:

    def program(gamerName:String): State[Deck, Player] = for {
      gamer <- gamerTakesTwoCards(gamerName)
      dealer <- dealerTakesTwoCards
      winner <- isBlackjack(gamer, dealer).fold(for {
        gamerFinal <- gamerDrawsCards(gamer)
        dealerFinal <- dealerDrawsCards(dealer, gamerFinal)
        winnerFinal = determineWinner(gamerFinal, dealerFinal)
      } yield winnerFinal)(State.pure[Deck, Player])
    } yield winner