2015-08-31 1 views
1

Я пытаюсь реорганизовать свой код SCALA в проекте (Play Framework 2.4), когда я пришел с этой идеей:Scala применения с частично определённая функция() не то же самое, как .Не()

(Для того, чтобы обеспечить минимальный рабочий пример, я изменил некоторые классы, например, я изменил результат и будущее [Результат] с 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) 
    } 
} 

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

Тогда я, хотя: я должен ограничивать кратную [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.

ответ

3

Поскольку вы определяете контекст, связанный в `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].

+0

Отлично, спасибо! – vicaba

+1

@vicaba Кроме того, вместо вызова 'apply', другим распространенным обходным путем является назначение частичного fuction для val сначала перед его вызовом. Например. 'val f = fold (аутентифицированный) (не прошедший проверку подлинности)' 'f (request)' – dcastro

Смежные вопросы