Асинхронное вычисление с проверкой в Scala с использованием Scalaz
Поскольку я пишу полностью асинхронную библиотеку для доступа к удаленному сервису (используя Play2.0), я используюPromise
а такжеValidation
создать неблокирующий вызов, который имеет тип, представляющий сбой и правильный результат сразу.
Promise
происходит от Play2-Scala, гдеValidation
исходит от скалаза.
Так вот тип примеров таких функций
f ::A => Promise[Validation[E, B]]
g :: B => Promise[Validation[E, C]]
Пока все хорошо, теперь, если я хочу их составить, я могу просто использовать тот факт, чтоPromise
представитьflatMap
так что я могу сделать это для понимания
for (
x <- f(a);
y <- g(b)
) yield y
Хорошо, я взял ярлык к моей проблеме здесь, потому что я не использовал повторноValidation
результаты в пределах для понимания. Так что, если я хочу использовать повторноx
вg
вот как я мог сделать
for (
x <- f(a); // x is a Validation
y <- x.fold(
fail => Promise.pure(x),
ok => g(ok)
)
) yield y
Достаточно справедливо, но этот тип шаблона будет загрязнять мой код снова и снова. Проблема здесь заключается в том, что я представляю собой своего рода двухуровневую монадическую структуру, такую какM[N[_]]
.
На данном этапе, есть ли какая-либо структура в f & # xB0; программирование, которое позволяет работать с такой структурой, легко пропуская уровень secong:
for (
x <- f(a); //x is a B
y <- g(b)
) yield y
Теперь ниже показано, как я добился чего-то подобного.
Я создал вид монадической структуры, которая объединяет два уровня в один, скажем,ValidationPromised
который сутенерPromise
введите два метода:
def /~> [EE >: E, B](f: Validation[E, A] => ValidationPromised[EE, B]): ValidationPromised[EE, B] =
promised flatMap { valid =>
f(valid).promised
}
def /~~>[EE >: E, B](f: A => ValidationPromised[EE, B]): ValidationPromised[EE, B] =
promised flatMap { valid =>
valid.fold (
bad => Promise.pure(KO(bad)),
good => f(good).promised
)
}
Это позволяет мне делать такие вещи
endPoint.service /~~> //get the service
(svc => //the service
svc.start /~~> (st => //get the starting elt
svc.create(None) /~~> //svc creates a new elt
(newE => //the created one
newEntry.link(st, newE) /~~> //link start and the new
(lnk => Promise.pure(OK((st, lnk, newE)))) //returns a triple => hackish
)
)
)
Как мы можем видеть/~~>
очень похоже наflatMap
но пропускает один уровень. Проблема заключается в многословии (именно поэтому «для понимания» существует в Scala и «делаю» в Haskell).
Еще один момент, который я/~>
что стоит какmap
также, но работает на втором уровне (вместо типа Valid -third уровень)
Итак, мой второй вопрос является следствием первого ... Я подхожу к устойчивому решению с этой конструкцией?
sorry to be that long