Ответ 1
trait Foo {
type MyFunction = (Int,Int) => Boolean
def checkInts(f: MyFunction)
def checkInts(f: Option[MyFunction])
}
Я надеюсь, что есть способ определить тип для функции в Scala.
Например, скажите, что я хочу функцию, которая принимает два Ints и возвращает логическое значение, я мог бы определить функцию, которая использует следующее:
def checkInts(f: (Int,Int) => Boolean) = {
// do stuff
}
Есть ли способ определить тип f? Тогда я мог бы сделать что-то вроде:
def checkInts(f: MyFunctionType)
или
def checkInts(f: Option[MyFunctionType])
trait Foo {
type MyFunction = (Int,Int) => Boolean
def checkInts(f: MyFunction)
def checkInts(f: Option[MyFunction])
}
Чтобы дополнить исходный ответ:
В некоторых более сложных случаях вы можете использовать структурные типы, которые также могут включать определения функций [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))
Это может быть очень удобно, если вы хотите обернуть свой аргумент асинхронной функции некоторой логикой, например транзакциями, подобными транзакциям.