2016-07-22 18 views
2

斯卡拉類型簽名與子失敗,我有以下的異常層次結構定義

/** 
    * Base class for all exceptions in this library 
    */ 
trait MyAkkaHttpException {} 

/** 
    * Thrown when there is a problem persisting data to a datastore 
    */ 
case class PersistenceException(message: String) 
    extends Exception(message: String) with MyAkkaHttpException 

/** 
    * Thrown when validation on an object fails 
    * @param errors 
    */ 
case class ValidationException(message: String, errors: List[String]) 
    extends Exception(message: String) with MyAkkaHttpException 

以下代碼:

class ContactFormService(contactFormPersistor: ContactFormPersistor) { 

    def handleForm(contactForm: ContactForm): ValidationNel[MyAkkaHttpException, String] = { 

    contactForm.validate() match { 
     case Success(_) => contactFormPersistor.persist(contactForm) 
     case Failure(e) => 
     new ValidationException(message = "Error validating contact form", 
      errors = e.toList).failureNel[String] 
    } 
    } 
} 
  • contactFormPersistor.persist返回ValidationNel[PersistenceException, String]
  • contactForm.validate()回報ValidationNel[String, Boolean]

問題是handleForm不會接受PersistenceExceptionValidationExceptionMyAkkaHttpException的子類。我需要做什麼才能正確認識到那些返回類型是有效的子類?

+0

使用'+',我相信。 – Elazar

+0

@Elazar我嘗試過,但它顯示爲語法錯誤。請你能寫一個答案嗎? – jbrown

+0

嘗試'ValidationNel [+ MyAkkaHttpException,String]' – Elazar

回答

2

嘗試將ValidationNel[MyAkkaHttpException, String]更改爲Validation[NonEmptyList[MyAkkaHttpException], String]。正如有人在評論中指出的那樣,它只是在第一個類型參數中不是協變的類型別名。

type ValidationNel[E, +X] = Validation[NonEmptyList[E], X] 

否則,NonEmptyListValidation在他們所有的參數都協。

編輯:

這可能取決於你的scalaz版本。至於我可以瀏覽的最新版本,它看起來像ValidationNelis no longer covariant in both arguments,但是it previously was。這種改變可能有一個很好的理由:準備好不能使用斯卡拉茲的ValidationNel函數。

0

的問題是你需要的ValidationNel第一類參數和Validation這個特殊的快捷協方差沒有設計這個協方差記*

基於我從我們的意見交換收集到的信息,我相信這是正確的前進方向。聲明自己的別名(或直接使用的類型)

type MyValidationNel[+E, +X] = Validation[NonEmptyList[E], X] 

*)我可是有一種感覺背後有沒有在E PARAM協方差(如scalaz通常知道做事情的理由的理由)

0

Either在左右兩邊都是協變的,所以我只是改用了它。