如何使这个功能变得纯净

时间:2018-02-15 10:09:26

标签: scala functional-programming purely-functional

我对纯函数的理解是函数的输出仅取决于输入。而且他们的参考是透明的。

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

  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不纯,那么如何让它变得纯粹

1 个答案:

答案 0 :(得分:1)

你非常接近,你已经使用Monadfor-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
}

然后这段代码完全纯粹且引用透明。