Scala, применяющая PartialFunction с помощью (), отличается от .apply().

Я пытаюсь реорганизовать свой код scala в проекте (Play Framework 2.4), когда у меня появилась эта идея:

(Чтобы предоставить минимальный рабочий пример, я изменил некоторые классы, например, я изменил Result и Future[Result] на Int и Option[Int] соответственно)

object ParFuncApply {

  trait CanBeAuthenticatedRequest[A]
  trait AuthenticatedRequest[A] extends CanBeAuthenticatedRequest[A]
  trait UnauthenticatedRequest[A] extends CanBeAuthenticatedRequest[A]


  private def fold[T](authenticated: (AuthenticatedRequest[_]) => T)
                             (unauthenticated: (UnauthenticatedRequest[_]) => T):
  PartialFunction[CanBeAuthenticatedRequest[_], T] = {
    case ar: AuthenticatedRequest[_] => authenticated(ar)
    case ur: UnauthenticatedRequest[_] => unauthenticated(ur)
  }

  def apply(request: CanBeAuthenticatedRequest[_])
           (authenticated: (AuthenticatedRequest[_]) => Int)
           (unauthenticated: (UnauthenticatedRequest[_]) => Int): Int = {
    fold(authenticated)(unauthenticated)(request)
  }

  def async(request: CanBeAuthenticatedRequest[_])
           (authenticated: (AuthenticatedRequest[_]) => Option[Int])
           (unauthenticated: (UnauthenticatedRequest[_]) => Option[Int]): Option[Int] = {
    fold(authenticated)(unauthenticated)(request)
  }
}

Приведенный выше код компилируется.

Затем я подумал: я должен ограничить параметризованные типы fold[T] Int и Option[Int], поэтому я добавил:

object ParFuncApply {

  trait CanBeAuthenticatedRequest[A]
  trait AuthenticatedRequest[A] extends CanBeAuthenticatedRequest[A]
  trait UnauthenticatedRequest[A] extends CanBeAuthenticatedRequest[A]

  sealed trait Helper[T]

  object Helper {
    implicit object FutureResultHelper extends Helper[Option[Int]]
    implicit object ResultHelper extends Helper[Int]
  }

  private def fold[T: Helper](authenticated: (AuthenticatedRequest[_]) => T)
                             (unauthenticated: (UnauthenticatedRequest[_]) => T):
  PartialFunction[CanBeAuthenticatedRequest[_], T] = {
    case ar: AuthenticatedRequest[_] => authenticated(ar)
    case ur: UnauthenticatedRequest[_] => unauthenticated(ur)
  }

  def apply(request: CanBeAuthenticatedRequest[_])
           (authenticated: (AuthenticatedRequest[_]) => Int)
           (unauthenticated: (UnauthenticatedRequest[_]) => Int): Int = {
    fold(authenticated)(unauthenticated)(request)
  }

  def async(request: CanBeAuthenticatedRequest[_])
           (authenticated: (AuthenticatedRequest[_]) => Option[Int])
           (unauthenticated: (UnauthenticatedRequest[_]) => Option[Int]): Option[Int] = {
    fold(authenticated)(unauthenticated)(request)
  }
}

Но этот код больше не компилируется, вместо этого, если я изменяю: fold(authenticated)(unauthenticated)(request) на fold(authenticated)(unauthenticated).apply(request) (я добавил явный вызов apply()), он компилируется. Почему это происходит? call() и .apply() для класса должны быть одинаковыми, не так ли?

Похоже, что компилятор запрашивает тип возвращаемого значения (Int или Option[Int]) для передачи в PartialFunction вместо типа CanBeAuthenticatedRequest.


person vicaba    schedule 31.08.2015    source источник


Ответы (1)


Поскольку вы определяете контекст, привязанный к `fold[T : Helper]', компилятор добавит еще один список параметров. Другими словами, привязка к контексту — это просто синтаксический сахар для:

private def fold[T](authenticated: (AuthenticatedRequest[_]) => T)
                   (unauthenticated: (UnauthenticatedRequest[_]) => T)
                   (implicit helper: Helper[T): PartialFunction[CanBeAuthenticatedRequest[_], T] 

поэтому, когда вы звоните

fold(authenticated)(unauthenticated)(request)

компилятор считает, что request должен быть явно заданным неявным Helper[T].

person Sascha Kolberg    schedule 31.08.2015
comment
@vicaba Кроме того, вместо вызова apply другим распространенным обходным путем является назначение частичной функции val перед ее вызовом. Например. val f = fold(authenticated)(unauthenticated) f(request) - person dcastro; 31.08.2015