2014-12-31 6 views
3

В функционального программирования в Scala главе 4 мы представлены следующие определения для map, getOrElse и flatMap для Option типа:flatMap в Scala

def map[B](f: A => B): Option[B] = this match { 
    case Some(x) => Some(f(x)) 
    case _ => None 
} 

def getOrElse[B>:A](default: => B): B = this match { 
    case Some(x) => x 
    case _ => default 
} 

def flatMap[B](f: A => Option[B]): Option[B] = 
    map(f) getOrElse None 

я получаю то, что flatMap делает, но я не не получится, как работает вызов map(f) в определении flatMap. f имеет A => Option[B] как его тип в flatMap, но мы как-то можем позвонить map, который ожидает какую-либо функцию типа A => B, с f. Разумеется, звонок getOrElse None является ключевым, но я не понимаю, как он позволяет нам звонить map(f) в flatMap.

ответ

4

При вызове flatMap и передать функции A => Option[B], flatMap вызовы map и передает ту же функцию, но B в flatMap не то же самое, что и в Bmap. Например, если вы передать некоторые

Int => Option[String] 

Тогда для map, B = Option[String] и вернется Option[Option[String]].

Таким образом, getOrElse в flatMap, чтобы получить волю, либо получить внутреннее Option[B], либо вернуть None.

+0

Имеет смысл ... но почему я получаю следующую ошибку, когда комментирую вызов getOrElse ------------------------ ------------------- тип несоответствие; [ошибка] найдено: A => fpinscala.errorhandling.Option [B] [ошибка] требуется: A => B [ошибка] карта (f) // getOrElse Нет --------- ------------------------------- Кажется, что вызов карты сбой – user772110

+0

Если вы удалите 'getOrElse', тогда у вас есть опция [Option [B]] 'вместо' Option [B] ' –

+0

Да, я понимаю, но почему вызов должен отображаться с ошибкой только потому, что я прокомментирую это. Я знаю, что вызов getOrElse необходим для flatMap для его «сглаживания», но почему вызов должен отображать уход. Похоже, что из сообщения об ошибке на карте говорится: «Вы не можете называть меня функцией с типом A => Option [B], мне нужно: A => B. Я интерпретирую ошибку компилятора неправильно? – user772110

2

B - это просто имя параметра типа переменной. Он имеет смысл только в пределах своей сферы. Другими словами, B в определениях map и flatMap не обязательно должны быть одинаковыми, они представляют собой совершенно разные параметры.

написал бы абсолютно то же самое:

def flatMap[C](f: A => Option[C]): Option[C] = 
    map(f) getOrElse None 

Теперь, в этом плане, легко видеть, что map используется здесь имеет Option[C] в качестве значения его параметра типа.

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