Подтвердить что ты не робот

Как определить тип функции в Scala?

Я надеюсь, что есть способ определить тип для функции в Scala.

Например, скажите, что я хочу функцию, которая принимает два Ints и возвращает логическое значение, я мог бы определить функцию, которая использует следующее:

def checkInts(f: (Int,Int) => Boolean) = {
  // do stuff
}

Есть ли способ определить тип f? Тогда я мог бы сделать что-то вроде:

def checkInts(f: MyFunctionType)

или

def checkInts(f: Option[MyFunctionType])
4b9b3361

Ответ 1

trait Foo {
  type MyFunction = (Int,Int) => Boolean

  def checkInts(f: MyFunction)
  def checkInts(f: Option[MyFunction])
}

Ответ 2

Чтобы дополнить исходный ответ:

В некоторых более сложных случаях вы можете использовать структурные типы, которые также могут включать определения функций [1], [2].

Что касается конкретных примеров и практического использования, функциональные типы можно было бы довольно хорошо использовать с Future, например, для передачи ExecutionContext и фактического выполнения асинхронной функции после ее передачи.

Обратите внимание, однако, что если у вас всегда есть доступный EC в исполняющем классе и, следовательно, вам не нужно его передавать, вы можете использовать аргументы по имени ("gimme just a Future result") [3].

Приведенный ниже черновой пример демонстрирует эту простую идею: у него есть тип функции только с ec и структурный тип, который также может принимать некоторые параметры для функции, которая будет выполнена. Он также показывает альтернативу с помощью функции по имени:

/** Define types in companion and sample functions that use them as args. */
class Fun(implicit ec: ExecutionContext) {
  import Fun._

  def foo(fun: SimplyFun): Future[String] = fun()
  def bar(fun: StructuredFun): Future[String] = fun.buzz(fun.bee)
  def byNameBaz(fun: => Future[String]) = fun
}

object Fun {
  type SimplyFun = ExecutionContext => Future[String]
  type StructuredFun = {
    def buzz(bee: Int)(implicit ec: ExecutionContext): Future[String]
    val bee: Int
  }
}

// (somewhere outside)
// example args could be instantiated as follows:
val simpleArg: SimplyFun = _ => Future.successful(String)
val structuredArg: StructuredFun = new {
  def buzz(bee: Int)(implicit ec: ExecutionContext) = Future.successful(s"$bee")
  val bee = 3
}

// ...and passed for execution along with the EC you like:
import scala.concurrent.ExecutionContext.Implicits.global
new Fun().foo(simpleArg)
new Fun().bar(structuredArg)
new Fun().byNameBaz(Future.failure(new RuntimeException))

Это может быть очень удобно, если вы хотите обернуть свой аргумент асинхронной функции некоторой логикой, например транзакциями, подобными транзакциям.