Функции с карри и фьючерсами в Scala - PullRequest
3 голосов
/ 06 июня 2019

Я изучаю Scala и хотел бы понять, как Futures может быть реализовано для карри функций

import scala.concurrent.{Await, Future}
import scala.concurrent.duration.Duration
import scala.concurrent.ExecutionContext.Implicits.global

object MainApp {

  def main(args: Array[String]): Unit = {

    val x = curriedMultiply(10) _ andThen Await.result(curriedAdd(10),Duration.Inf)

    println(x(2))



  }

  def curriedAdd(x: Int)(y: Int) : Future[Int]= Future {
    x + y
  }

  def curriedMultiply(x: Int)(y: Int) : Future[Int] = Future {
    x * y
  }

}

Я получаю приведенную ниже ошибку компилятора при получении значения

Type mismatch, expected: Awaitable[NotInferedT], actual: Int => Future[Int]

1 Ответ

6 голосов
/ 06 июня 2019

Я предполагаю, что вы пытаетесь составить две функции типа Int => Future[Int] (тип обеих функций после применения первого аргумента), затем выполнить функцию результата для параметра 2 и дождаться результата. Если мое предположение верно, то вы не можете просто использовать andThen, потому что вам нужно смоделировать поведение, когда домен (тип ввода) и совместный домен (тип вывода) функций не совпадают.

Вы можете пойти своим путем, сделав так:

def combine(x:Int) = curriedMultiply(10)(x) flatMap (curriedAdd(10))
//or: val combine  = curriedMultiply(10)(_:Int) flatMap curriedAdd(10)

val y = Await.result(combine(2),Duration.Inf)

println(y)

или используйте библиотеку cats, потому что функции типа Int => Future[Int] являются Kleisli функциями, поэтому вы можете их составлять:

import cats.data.Kleisli
import cats.implicits._

val kfk = Kleisli(curriedAdd(10)) compose Kleisli(curriedMultiply(10))

val x = Await.result(kfk(2),Duration.Inf)

println(x)

Не могли бы вы объяснить, как здесь работает плоская карта.

Следующее происходит, когда вы применяете функцию combine к аргументу 2:

  1. curriedMultiply(10)(2) возвращает Future[Int], содержащее 10 * 2 значение (Future(10 * 2))
  2. curriedAdd(10) возвращает Int => Future[Int] функцию, которая y:Int => Future(10 + y)
  3. Теперь у вас есть Future(10 * 2).flatMap(y => Future(10 + y))
  4. flatMap возвращает Future, созданное функцией его аргументов. где y - это значение, полученное с помощью левой Future расчетной величины 20
...