2015-12-02 2 views
0

У меня возникли проблемы с расшифровкой следующей функции. В частности, линия flatMap - где «aa» и «bb»; переменные, исходящие, и как это выполняется? Может быть, если кто-то может объяснить словами, что происходит с этим кодом, это было бы полезно. Я просто очень стараюсь читать этот синтаксис.Как читать этот flatMap-код?

def map2[EE >: E, B, C](b: Either[EE, B])(f: (A, B) => C): Either[EE, C] = 
    this flatMap(aa => b map (bb => f(aa, bb))) 

Вот функция flatMap:

def flatMap[EE >: E, B](f: A => Either[EE, B]): Either[EE, B] = this match { 
    case Right(r) => f(r) 
    case Left(e) => Left(e) 
} 

и карта:

def map[B](f: A => B): Either[E, B] = this match { 
    case Right(r) => Right(f(r)) 
    case Left(e) => Left(e) 
} 

ответ

3

Похоже, все эти функции определены для класса Либо. Либо может быть в двух «состояниях» - правильном значении и левом, что интерпретировало заднюю ошибку.

Переходим от определения карты. Мы либо параметризированы с типом A. map принимает функцию преобразования типа A в B. Таким образом, функция карты проверяет, является ли значение правильным, тогда она применяет заданную функцию f к правильному значению, обертывает ее правым и возвратным. Если ошибка, то просто верните ошибку.

Right[String, Int](4).map(_*3)  // gives Right(12) 
Left[String, Int]("error").map(_*3) // gives Left("error") 

flatMap похожа на карту, но принимает функция преобразования типа A в любом из правого типа В, поэтому в отличие от карты нам не нужно, чтобы обернуть правильное значение

Right[String, Int](5).flatMap(item => Right(item*3))  //gives Right(15) 
Left[String, Int]("error").flatMap(item => Right(item*3)) //gives Left("error") 

Как определено, map2 принимает экземпляр Либо b и функцию, преобразуя пару значений типов A и B в третье значение C и возвращая результат, завернутый в Либо. Давайте подробнее рассмотрим, как это реализовано.

this.flatMap(aa => b map (bb => f(aa, bb)))  

позволяет переписать его с определением flatMap:

this.match { 
    case Right(r) => b.map (bb => f(r, bb)) 
    case Left(e) => Left(e) 
} 

и применить карту:

this.match { 
    case Right(r) => { 
    b match { 
     case Right(br) => Right(f(r, br)) 
     case Left(be) => Left(be) 
    } 
    } 
    case Left(e) => Left(e) 
} 

Итак, есть три пути:

if right a and right b then apply function(a,b) 
if right a and error b then error(b) 
if error a then error a 

Примеры:

Right(7).map2(Right(4)){case (a,b) => a*b} // gives Right(28) 
Right(7).map2(Left[String, Int]("failed")){case (a,b) => a*b} //gives Left("failed") 
Left[String, Int]("error").map2(Left[String, Int]("failed")){case (a,b) => a*b} //gives Left("error") 

Edit: Внутренняя функция объяснения

Вы должны перейти к функции flatMap с типом:

A => Either[EE, C] 

Это означает «взять аргумент типа А и преобразовать его результат типа: либо [EE, C]»

, чтобы вы могли определить:

def map2[EE >: E, B, C](b: Either[EE, B])(f: (A, B) => C): Either[EE, C] = {  
    def func(aa:A):Either[EE, C] = { 
    b map (bb => f(aa, bb)) 
    } 
    this flatMap(func) 
} 
+0

Я думаю, основная проблема, которую я имею, это синтаксис: 'this flatMap (aa => b map (bb => f (aa, bb)))' что такое aa в этом случае и откуда оно взялось? – jcm

+0

Добавлены некоторые пояснения о внутренней функции – Nyavro

+0

Хм, но я до сих пор не понимаю, как «эта» ссылка передается в func? – jcm

Смежные вопросы