【问题标题】:How do I implement a pure functional architecture for a project containing objects that do change over time with Scala and scalaz如何为包含随时间变化的对象的项目实现纯功能架构,使用 Scala 和 scalaz
【发布时间】:2017-05-29 08:43:15
【问题描述】:

我有一个项目,我正在实施自动售货机。我有一个对象 VendingMachine,里面有另一个对象,叫做 CoinOp。我希望 CoinOp 对象接受各种价值的硬币。 VendingMachine 可以要求 CoinOp 告诉它用户输入了多少钱。为了让它真正发挥作用,CoinOp 必须能够改变它里面的货币数量。

自动售货机看起来像这样:

class VendingMachine {
    val coinOp = new CoinOp()
}

我想以一种功能性的方式来做这件事,它会立即删除 CoinOp 的这个实现作为一个选项:

class CoinOp {
    var money = 0.0f

    def addCoins(amount: Float) = money += amount
}

相反,我需要做这样的事情:

case class CoinOp(money: Float) {
    def addCoins(amount: Float): CoinOp = CoinOp(money + amount)
}

我知道我可以使用 scalaz 来做这样的事情。 scalaz 中的实现并不是这个问题的真正重点。

我的问题是:鉴于我可以在功能上更新 CoinOp 拥有的金额,我如何显示发生变化的 VendingMachine?

在 addCoins 中创建新的 CoinOp 对象非常棒,但它是一个新对象,它不会改变 VendingMachine 引用的对象。这是良好的持久性,都是函数式编程的一部分。但是,我需要 VendingMachine 使用 addCoins() 创建的对象,而不是类定义中的对象。我该怎么做?

我唯一能想到的就是将 VendingMachine 中的 coinOp 对象设为 var,然后我可以设置它以响应对 CoinOp#addCoins 的调用。但这对我来说似乎不是一个好的解决方案。

有人可以解释一下如何设置吗?

【问题讨论】:

  • 看来您正在寻找 State Monad。

标签: scala functional-programming scalaz


【解决方案1】:

如果您想进行函数式编程,请尽可能坚持使用没有副作用和不可变结构的方法,就像您使用您的方法一样

case class CoinOp(money: Float) {
  def addCoins(amount: Float): CoinOp = CoinOp(money + amount)
  def addCoins(amount: CoinOp): CoinOp = CoinOp(money + amount.money)
}

因此,正如您所说,在调用 addCoins 方法时,您将返回新的 CoinOp 实例。

但这里的问题是你的任务。拥有自动售货机意味着您有一些需要维护的状态。不幸的是,状态是var

因此,如果您不需要线程安全,您只需创建 CoinOp 类型的私有变量,并在添加资金时 - 您将 CoinOp 的另一个实例分配给此 var。这样,您的 CoinOp 类将不可变,但 VendingMachine 将具有状态并且是可变的。

class VendingMachine{
  var funds: CoinOp = CoinOp(0)

  def addFunds(amount: CoinOp): CoinOp = {
    funds = funds.addCoins(amount.money)
    // or rather use addCoins(CoinOP):
    // funds = funds.addCoins(amount)
  }
}

如果您想同步访问您的资金状态 - Scala 方式是 Akka Actor,将您的状态保持在自身内部

【讨论】:

  • 我觉得这根本解决不了问题。它不会删除状态,只是将其移动到其他地方。
  • 据我了解 - 状态是某些问题的本质。这就是为什么存在像 akka actor 这样的库的原因。所以拥有状态 - 是 VendingMachine 性质的一部分。你需要处理它。
  • OP 没有询问有关在并发上下文中管理状态的任何内容,这就是您首先要使用 Actors 的原因。
猜你喜欢
  • 2017-12-29
  • 2019-08-24
  • 2017-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多