2013-07-17 6 views
6

私のアプリケーションでScalaz 7検証を使用しようとしています。しかし、私は失敗を合体させるために|@|応募者を得ることに問題があります。ここで私が持っているコードです:Scalazバリデーションと適用ファンクタ| @ |動作していません

type ValidationResult = ValidationNel[String, Unit] 

def validate[A: ClassTag](instance: A, fieldNames: Option[Seq[String]] = None): ValidationResult = { 
    val fields = classTag[A].runtimeClass.getDeclaredFields 
    val fieldSubset = fieldNames match { 
     case Some(names) => fields.filter { field => names.contains(field.getName) } 
     case None => fields 
    } 
    fieldSubset.map { 
     field => field.getAnnotations.toSeq.map { 
      field.setAccessible(true) 
      val (name, value) = (field.getName, field.get(instance)) 
      field.setAccessible(false) 
      annotation => annotation match { 
       case min: Min => minValidate(name, value, min.value()) 
       case size: Size => sizeValidate(name, value, size.min(), size.max()) 
      } 
     } 
    }.flatten[ValidationResult].foldLeft(().successNel[String])(_ |@| _) 
} 

minValidatesizeValidate機能だけでValidationResultsを返します。

問題は、このコードはコンパイルされないことです。エラーメッセージは次のとおりです:

私はそれが何を意味するのか分かりません...私はスカラーにさらにタイプ情報を与える必要がありますか?

私が達成しようとしているのは、すべてのフィールドがsuccessNelの場合はそれを返し、それ以外の場合はすべてfailureNelの組み合わせを返します。

Scalazの前のバージョンから|@|が変更されていますか?たとえ私が次のようなことをしたとしても:

().successNel |@|().successNel 

私は同じエラーが発生します。

アップデートは私がScalazソースの周り突っつい開始し、私は私がやりたいように見える+++を発見しました。

+++|@|の違いは何ですか?

答えて

10

Scalazのアプリケーションビルダー構文(|@|)は、関数をアプリケーションファンクタに「持ち上げる」方法を提供します。例えば、我々は次のような結果があるとします。

val xs: ValidationNel[String, List[Int]] = "Error!".failNel 
val ys: ValidationNel[String, List[Int]] = List(1, 2, 3).success 
val zs: ValidationNel[String, List[Int]] = List(4, 5).success 

我々はこのようなValidationにリスト連結関数(++)を持ち上げることができます。

scala> println((ys |@| zs)(_ ++ _)) 
Success(List(1, 2, 3, 4, 5)) 

scala> println((xs |@| ys)(_ ++ _)) 
Failure(NonEmptyList(Error!)) 

scala> println((xs |@| xs)(_ ++ _)) 
Failure(NonEmptyList(Error!, Error!)) 

この構文は少し変な-、それは非常にとは異なりますですどのように関数をHaskellの応用ファンクタに持ち上げるのか、そしてこれは主にScalaのかなり愚かな型推論システムを凌駕するように設計されています。詳細については、my answer hereまたはblog post hereを参照してください。

xs |@| ysは実際には何も意味しません。それは本質的に、それがアプリケーションファンクタに持ち込まれて自分自身に適用される関数に適用されるのを待っている引数リストです。

Validation+++は、それがクリーチャー - (あなたが同等+++の代わりに、ここでScalazの半群演算子|+|を使用できることに注意してください)タイプのSemigroupインスタンスのためだけの追加操作だの非常に簡単なものです。あなたは一致するセミグループタイプを持つValidationの結果を2つ与え、もう1つはValidationであり、それほどひどいものはありませんApplyOpsものです。Validationの半群のためのサイドノートとして


、この場合の加算動作は右側用の半群の動作と同様でValidationに持ち上げられる:

scala> (xs |+| ys) == (xs |@| ys)(_ |+| _) 
res3: Boolean = true 

これはないであろうしかし、常にそうである(例えば、\/ではなく、semigroupはエラーを蓄積するが、アプリケーションファンクタはそうではない)。

関連する問題