【问题标题】:How to make this function pure如何使这个函数纯粹
【发布时间】:2018-07-26 01:15:15
【问题描述】:

我对纯函数的理解是函数的输出只取决于输入。而且它们在引用上是透明的。

但是在我们的代码中会出现副作用。下面是一个例子

  import scala.concurrent.Future
  case class Customer(fName: String, lName: String)
  case class Order(orderId: Int, item: String, quantity: Int)
  case class Shipment(shipmentId: Int, orderId: Int, address: String)

  trait CustomerRepo {
    def findCustomer(userId: String): Future[Customer] = ???
    def findLastOrder(customer: Customer): Future[Order] = ???
    def findShipment(orderId: Int): Future[Shipment] = ???
  }

  class ShoppingApp(customerRepo: CustomerRepo) {

    def getLastShipment(userId: String): Future[Shipment] = {
      for {
        customer <- customerRepo.findCustomer(userId)
        lastOrder <- customerRepo.findLastOrder(customer)
        shipment <- customerRepo.findShipment(lastOrder.orderId)
      } yield shipment
    }

  }

上面是一个基本的例子,我们做了多个副作用(调用数据库)。

getLastShipment 返回一个 Future。这样做是不是一个纯函数。

如果 getLastShipment 不是纯的,那么如何使它成为纯???

【问题讨论】:

  • getLastShipment 没有任何不纯的地方。唯一的“问题”是您正在使用Future,它被热切地评估并破坏了RT。除此之外,你很好。
  • 期货与整个纯粹的事物背道而驰。除此之外,我认为纯 getLastShipment 函数不应该依赖于上下文,这意味着它应该明确要求 CustomerRepo 作为函数参数。

标签: scala functional-programming purely-functional


【解决方案1】:

你已经很接近了,你已经在使用Monads 和for-comprehensions 的正确道路上,但是,Future 从根本上来说是有副作用的,因为它不会暂停它的评估。 (有关更多信息,请参阅我的回答 here。 如果您将功能切换为使用cats.effect.IO

def getLastShipment(userId: String): IO[Shipment] = {
  for {
    customer <- customerRepo.findCustomer(userId)
    lastOrder <- customerRepo.findLastOrder(customer)
    shipment <- customerRepo.findShipment(lastOrder.orderId)
  } yield shipment
}

那么这段代码是完全纯粹的,并且是引用透明的。

【讨论】:

  • 感谢@luka-jacobowit 的回复。我从中了解到的是,如果我们将副作用放在容器中(选项,未来 - 好吧,它并不完美,函子等)。这将使我的方法 getLastShipment 纯粹......我只是在努力理解如何将副作用放在容器中使其变得纯粹......也许你能指出我的一些材料......谢谢
  • 当然@abhishek,也许这篇文章可以帮助你underscore.io/blog/posts/2015/04/28/… :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 2016-12-17
相关资源
最近更新 更多