Scalaz 6を学びながら、検証を返すタイプセーフなリーダーを作成しようとしています。これが私の新しいタイプです:
type ValidReader[S,X] = (S) => Validation[NonEmptyList[String],X]
type MapReader[X] = ValidReader[Map[String,String],X]
そして、intとstrings(*)のマップリーダーを作成する2つの関数があります。
def readInt( k: String ): MapReader[Int] = ...
def readString( k: String ): MapReader[String] = ...
次のマップがあるとします。
val data = Map( "name" -> "Paul", "age" -> "8" )
名前と年齢を取得するために2つのリーダーを作成できます。
val name = readString( "name" )
val age = readInt( "age" )
println( name(data) ) //=> Success("Paul")
println( age(data) ) //=> Success(8)
Boy
すべて正常に動作しますが、インスタンスを構築するために両方のリーダーを作成したいと思います。
case class Boy( name: String, age: Int )
私の最善の策は次のとおりです。
val boy = ( name |@| age ) {
(n,a) => ( n |@| a ) { Boy(_,_) }
}
println( boy(data) ) //=> Success(Boy(Paul,8))
期待どおりに機能しますが、2つのレベルのアプリケーションビルダーでは表現が厄介です。次の構文を機能させる方法はありますか?
val boy = ( name |@| age ) { Boy(_,_) }
(*)https://gist.github.com/1891147の完全で実行可能な実装
更新:上記の行またはダニエルの提案を試したときに表示されるコンパイラエラーメッセージは次のとおりです。
[error] ***/MapReader.scala:114: type mismatch;
[error] found : scalaz.Validation[scalaz.NonEmptyList[String],String]
[error] required: String
[error] val boy = ( name |@| age ) { Boy(_,_) }
[error] ^