TL; DR은 최종 예제로 직접 이동
나는 노력하고 요약 할 것이다.
정의
for
이해가 결합 구문 바로 가기입니다 flatMap
및 map
읽기에 대한 이유 쉽다 방법이다.
일을 조금 단순화하고 class
앞서 언급 한 두 가지 방법을 모두 제공 하는 모든 것이 a라고 할 수 있다고 가정 하고 내부 유형이있는 a를 의미하는 monad
기호 M[A]
를 사용할 것 입니다.monad
A
예
일반적으로 볼 수있는 몇 가지 모나드는 다음과 같습니다.
List[String]
어디
M[X] = List[X]
A = String
Option[Int]
어디
Future[String => Boolean]
어디
M[X] = Future[X]
A = (String => Boolean)
map 및 flatMap
일반 모나드에서 정의 됨 M[A]
def map(f: A => B): M[B]
def flatMap(f: A => M[B]): M[B]
예 :
val list = List("neo", "smith", "trinity")
val f: String => List[Int] = s => s.map(_.toInt).toList
list map f
>> List(List(110, 101, 111), List(115, 109, 105, 116, 104), List(116, 114, 105, 110, 105, 116, 121))
list flatMap f
>> List(110, 101, 111, 115, 109, 105, 116, 104, 116, 114, 105, 110, 105, 116, 121)
표현을 위해
<-
기호를 사용하는 표현식의 각 행 flatMap
은 마지막 호출 로 변환 되는 마지막 행을 제외하고 는 호출로 변환됩니다. map
여기서 왼쪽의 "바운드 기호"는 매개 변수로 인수 함수에 전달됩니다 (what 이전에 f: A => M[B]
) :
for {
bound <- list
out <- f(bound)
} yield out
list.flatMap { bound =>
f(bound).map { out =>
out
}
}
list.flatMap { bound =>
f(bound)
}
list flatMap f
하나만있는 for-expression 은 인수로 전달 된 표현식이 <-
있는 map
호출로 변환됩니다 .
for {
bound <- list
} yield f(bound)
list.map { bound =>
f(bound)
}
list map f
이제 요점
당신이 볼 수 있듯이, map
작업은 원래의 "모양"을 보존 monad
같은이 위해 발생하므로, yield
식 : A는 List
남아 List
의 조작에 의해 변환 된 내용으로 yield
.
반면에의 각 바인딩 선 for
은 연속 된의 구성 일 뿐이며 monads
단일 "외부 모양"을 유지하려면 "평평하게 만들어야"합니다.
잠시 동안 각 내부 바인딩이 map
호출 로 변환 되었지만 오른손이 동일한 A => M[B]
기능이라고 가정 M[M[B]]
하면 이해의 각 줄에 대해 a 로 끝납니다 .
전체 for
구문 의 목적은 결론 변환을 수행 할 수A => M[B]
있는 최종 map
연산을 추가하여 연속적인 모나드 연산 (즉, "모나드 형태"에서 값을 "리프트"하는 연산)의 연결을 쉽게 "평탄화" 하는 것입니다 .
이것이 기계적 방식으로 적용되는 번역 선택의 논리, 즉 n
flatMap
단일 map
호출로 종료되는 중첩 호출을 설명하기를 바랍니다 .
인위적인 설명 예제
는 for
구문 의 표현력을 보여주기위한 것입니다.
case class Customer(value: Int)
case class Consultant(portfolio: List[Customer])
case class Branch(consultants: List[Consultant])
case class Company(branches: List[Branch])
def getCompanyValue(company: Company): Int = {
val valuesList = for {
branch <- company.branches
consultant <- branch.consultants
customer <- consultant.portfolio
} yield (customer.value)
valuesList reduce (_ + _)
}
유형을 추측 할 수 있습니까 valuesList
?
이미 말했듯이의 모양은 monad
이해를 통해 유지되므로 List
in으로 시작 company.branches
하고 List
.
대신 내부 유형이 변경되고 다음 yield
표현식에 의해 결정됩니다.customer.value: Int
valueList
이어야합니다 List[Int]