После просмотра анонса Ника Партиджа о выводе scalaz, Мне пришлось посмотреть на этот пример, который просто потрясающий:
import scalaz._
import Scalaz._
def even(x: Int) : Validation[NonEmptyList[String], Int]
= if (x % 2 ==0) x.success else "not even: %d".format(x).wrapNel.fail
println( even(3) <|*|> even(5) ) //prints: Failure(NonEmptyList(not even: 3, not even: 5))
Я пытался понять, что делает метод <|*|>
, вот исходный код:
def <|*|>[B](b: M[B])(implicit t: Functor[M], a: Apply[M]): M[(A, B)]
= <**>(b, (_: A, _: B))
ОК, это довольно запутанно (!), но оно ссылается на метод <**>
, который объявляется следующим образом:
def <**>[B, C](b: M[B], z: (A, B) => C)(implicit t: Functor[M], a: Apply[M]): M[C]
= a(t.fmap(value, z.curried), b)
Итак, у меня есть несколько вопросов:
- Как получилось, что метод принимает более высокий тип одного параметра типа (
M[B]
), но может быть передан aValidation
(который имеет два типа пареметров)? - Синтаксис
(_: A, _: B)
определяет функцию(A, B) => Pair[A,B]
, которую ожидает второй метод: что происходит с Tuple2/Pair в случае отказа? Там нет кортежа!