Изучая 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] ^
Applicative[G]
иApplicative[F]
подразумеваетApplicative[[x]F[G[x]]
. В scalaz 7Applicative#compose
свидетельствует об этом факте. Для начала работайте напрямую с классами типов, а не с использованием синтаксиса|@|
. - person retronym   schedule 23.02.2012apply
явно? Как 2_? - person Daniel C. Sobral   schedule 23.02.2012