Как составить функцию для аппликативов с помощью scalaz

Изучая Scalaz 6 , я пытаюсь написать типобезопасные программы чтения, возвращающие проверки. Вот мои новые типы:

type ValidReader[S,X] = (S) => Validation[NonEmptyList[String],X]
type MapReader[X] = ValidReader[Map[String,String],X]

и у меня есть две функции, создающие картридеры для целых чисел и строк (*):

def readInt( k: String ): MapReader[Int] = ...
def readString( k: String ): MapReader[String] = ...

Учитывая следующую карту:

val data = Map( "name" -> "Paul", "age" -> "8" )

Я могу написать двух читателей, чтобы получить имя и возраст:

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))

Он работает, как ожидалось, но выражение неудобное с двумя уровнями прикладных строителей. Есть ли способ заставить работать следующий синтаксис?

  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]                                    ^

11
задан paradigmatic 23 February 2012 в 15:35
поделиться