在 Scala 中的功能步骤之间传递状态
Passing state between functional steps in Scala
有没有更好的方法在步骤之间传递状态。
例如,每次从牌组中取出一张牌时,我们都必须创建一个新的牌组 return 以便下一步可以使用它等
有没有更好的方法,例如使用猫来做到这一点?
trait BlackjackSteps {
def gamerTakesTwoCards(deck: Deck): (Gamer, Deck)
def dealerTakesTwoCards(deck: Deck): (Dealer, Deck)
def isBlackjack(gamer: Gamer, dealer: Dealer): Option[Player]
def gamerToDrawCards(gamer: Gamer, deck: Deck): Gamer
def dealerToDrawCards(dealer: Dealer, deck: Deck, gamer: Gamer): Dealer
def determineWinner(gamer: Gamer, dealer: Dealer): Player
}
游戏:
- 玩家和荷官玩
- 他们都抽了两张牌
- 如果没有 21 名获胜者
- 玩家一直抽牌到 17 岁
- 不超过 21 分的最高玩家获胜
编辑 -----
感谢您的回复。我只是想看看人们对这种做法的看法?
这个怎么样?
trait CardPicker {
def pick(numberCards:Int): List[Card]
}
abstract class BlackjackSteps(cardPicker: CardPicker) {
def gamerTakesTwoCards(gamer: Gamer): Gamer = {
gamer.copy(cards = cardPicker.pick(2))
}
def dealerTakesTwoCards(dealer: Dealer): Dealer = {
dealer.copy(cards = cardPicker.pick(2))
}
def isBlackjack(gamer: Gamer, dealer: Dealer): Option[Player] = {
if(gamer.isBlackjack) Some(gamer)
else if(dealer.isBlackjack) Some(dealer)
else None
}
def gamerToDrawCards(gamer: Gamer): Gamer = {
def drawCards(gamerPickingCards: Gamer): Gamer = gamer match {
case _ if(gamerPickingCards.points < drawThreshold) =>
drawCards(Gamer(gamerPickingCards.name, gamerPickingCards.cards ++ cardPicker.pick(1)))
case _ => gamerPickingCards
}
drawCards(gamer)
}
def dealerToDrawCards(dealer: Dealer, gamer: Gamer): Dealer = {
def drawCards(dealerPickingCards: Dealer): Dealer = dealer match {
case _ if(dealerPickingCards.points < gamer.points) =>
drawCards(Dealer(dealerPickingCards.name, dealerPickingCards.cards ++ cardPicker.pick(1)))
case _ => dealerPickingCards
}
drawCards(dealer)
}
def determineWinner(gamer: Gamer, dealer: Dealer): Player = {
if(gamer.points == dealer.points || gamer.points > dealer.points) gamer
else dealer
}
}
这里CardPicker有副作用,我们可以延迟到世界末日。
这也太疯狂了吧?
这听起来像是 State
monad 的一个很好的用例。以下内容可以帮助您入门:
trait BlackjackSteps {
def gamerTakesTwoCards: State[Deck, Gamer]
def dealerTakesTwoCards: State[Deck, Dealer]
def isBlackjack(gamer: Gamer, dealer: Dealer): State[Deck, Option[Player]]
def gamerToDrawCards(gamer: Gamer): State[Deck, Gamer]
def dealerToDrawCards(dealer: Dealer, gamer: Gamer): State[Deck, Dealer]
def determineWinner(gamer: Gamer, dealer: Dealer): State[Deck, Player]
}
def gamerTakesTwoCards: State[Deck, Gamer] =
State { oldDeck =>
val gamer = f(oldDeck)
val newDeck = g(oldDeck)
(newDeck, gamer)
}
您可以查看 Cats 官方文档以了解更多信息:
https://typelevel.org/cats/datatypes/state.html
有没有更好的方法在步骤之间传递状态。
例如,每次从牌组中取出一张牌时,我们都必须创建一个新的牌组 return 以便下一步可以使用它等
有没有更好的方法,例如使用猫来做到这一点?
trait BlackjackSteps {
def gamerTakesTwoCards(deck: Deck): (Gamer, Deck)
def dealerTakesTwoCards(deck: Deck): (Dealer, Deck)
def isBlackjack(gamer: Gamer, dealer: Dealer): Option[Player]
def gamerToDrawCards(gamer: Gamer, deck: Deck): Gamer
def dealerToDrawCards(dealer: Dealer, deck: Deck, gamer: Gamer): Dealer
def determineWinner(gamer: Gamer, dealer: Dealer): Player
}
游戏:
- 玩家和荷官玩
- 他们都抽了两张牌
- 如果没有 21 名获胜者
- 玩家一直抽牌到 17 岁
- 不超过 21 分的最高玩家获胜
编辑 -----
感谢您的回复。我只是想看看人们对这种做法的看法?
这个怎么样?
trait CardPicker {
def pick(numberCards:Int): List[Card]
}
abstract class BlackjackSteps(cardPicker: CardPicker) {
def gamerTakesTwoCards(gamer: Gamer): Gamer = {
gamer.copy(cards = cardPicker.pick(2))
}
def dealerTakesTwoCards(dealer: Dealer): Dealer = {
dealer.copy(cards = cardPicker.pick(2))
}
def isBlackjack(gamer: Gamer, dealer: Dealer): Option[Player] = {
if(gamer.isBlackjack) Some(gamer)
else if(dealer.isBlackjack) Some(dealer)
else None
}
def gamerToDrawCards(gamer: Gamer): Gamer = {
def drawCards(gamerPickingCards: Gamer): Gamer = gamer match {
case _ if(gamerPickingCards.points < drawThreshold) =>
drawCards(Gamer(gamerPickingCards.name, gamerPickingCards.cards ++ cardPicker.pick(1)))
case _ => gamerPickingCards
}
drawCards(gamer)
}
def dealerToDrawCards(dealer: Dealer, gamer: Gamer): Dealer = {
def drawCards(dealerPickingCards: Dealer): Dealer = dealer match {
case _ if(dealerPickingCards.points < gamer.points) =>
drawCards(Dealer(dealerPickingCards.name, dealerPickingCards.cards ++ cardPicker.pick(1)))
case _ => dealerPickingCards
}
drawCards(dealer)
}
def determineWinner(gamer: Gamer, dealer: Dealer): Player = {
if(gamer.points == dealer.points || gamer.points > dealer.points) gamer
else dealer
}
}
这里CardPicker有副作用,我们可以延迟到世界末日。
这也太疯狂了吧?
这听起来像是 State
monad 的一个很好的用例。以下内容可以帮助您入门:
trait BlackjackSteps {
def gamerTakesTwoCards: State[Deck, Gamer]
def dealerTakesTwoCards: State[Deck, Dealer]
def isBlackjack(gamer: Gamer, dealer: Dealer): State[Deck, Option[Player]]
def gamerToDrawCards(gamer: Gamer): State[Deck, Gamer]
def dealerToDrawCards(dealer: Dealer, gamer: Gamer): State[Deck, Dealer]
def determineWinner(gamer: Gamer, dealer: Dealer): State[Deck, Player]
}
def gamerTakesTwoCards: State[Deck, Gamer] =
State { oldDeck =>
val gamer = f(oldDeck)
val newDeck = g(oldDeck)
(newDeck, gamer)
}
您可以查看 Cats 官方文档以了解更多信息: https://typelevel.org/cats/datatypes/state.html