이 용어를 여기에서 실행하십시오.
http://www.codemesh.io/codemesh2014/viktor-klang
"우리는 Flow API (리프트 된 표현)와 리프팅 된 표현을 실행 표현 (Flow Materialization)으로 변환하는 플러그 가능한 방법을 보여줄 것입니다."
인터넷 검색은별로 도움이되지 않았습니다.
이 용어를 여기에서 실행하십시오.
http://www.codemesh.io/codemesh2014/viktor-klang
"우리는 Flow API (리프트 된 표현)와 리프팅 된 표현을 실행 표현 (Flow Materialization)으로 변환하는 플러그 가능한 방법을 보여줄 것입니다."
인터넷 검색은별로 도움이되지 않았습니다.
답변:
Flow API에 익숙하지 않습니다.
"리프팅"이라는 용어는 범주 이론에서 비롯됩니다. Haskell 또는 Scala와 같은 프로그래밍 언어에서 lift
함수는 함수를 취하고 A => B
어떤 식 으로든 마술을 수행하여 해제 된 함수 F[A] => F[B]
를 functor 또는 monad에 적용 할 수 있습니다 F[A]
.
스칼라 Seq
컨테이너 를 사용하는 구체적인 예 : function def double(x: Int): Int = 2 * x
과 sequence 가 있다고 가정하십시오 val xs = Seq(1, 2, 3)
. double(xs)
호환되지 않는 유형으로 인해 우리는 할 수 없습니다 . 우리가를 얻는다면 val doubleSeq = liftToSeq(double)
, 우리는 할 수있는 doubleSeq(xs)
평가하는 Seq(2, 4, 6)
. 여기에서 liftToSeq
구현할 수 있습니다
def liftToSeq[A, B](f: A => B): (Seq[A] => Seq[B]) =
(seq: Seq[A]) => seq.map(f)
Seq(…)
생성자는 값을 리프트 리프팅 동작으로 볼 수있다 1, 2, 3
에 Seq
따라서 우리가 이러한 값에 대한 목록 추상화를 사용할 수 있도록 인스턴스입니다.
Monads는 수밀하지만 구성 가능한 인터페이스를 제공하여 어떤 유형의 내부 작업을 캡슐화 할 수 있습니다. 해제 된 표현을 사용하면 계산에 대한 추론을 쉽게 할 수 있습니다. 이러한 추상화를 사용한다는 것은 추상화 된 특정 정보에 대한 지식을 잃는다는 것을 의미하지만, 적절한 실행 표현을 찾는 데있어 효율적인 구현을 제공하는 데 필요합니다.
+
다음과 같이 정의 된 연산자가 있다고 가정하십시오 int + int --> int
. 해제 가능 널 (null-to-nullable) 연산자 int? + int? --> int?
의 의미는 "피연산자 중 하나가 널 (null)이면 응답이 널 (null)이면 그렇지 않으면 값에 대해 리프트되지 않은 연산자를 사용하십시오"라는 의미를 갖습니다.
F
는 않지만 유형 생성자 인 경우 F[A]
구성된 유형 중 하나입니다. 그렇다면이 네 가지 유형에 대해 말하는 것이 왜 잘못 되었습니까? (물론 두 유형과 하나의 유형 생성자가 동일하게 괜찮을 것입니다)
물론 리프트 라는 용어 는 상황에 따라 다른 의미를 가질 수 있습니다.
일반 프로그래밍 에서는 다음 상위 레벨로 추상화하는 프로세스를 설명합니다. 예를 들어, 코드 유형은 int
, 코드 유형은 두 가지가 있습니다 float
. 이 코드를 리프팅하는 것은 제네릭 형식과 방법을하는 주형과 같은 의미 T
모두를 위해 작동 int
하고 float
.
나는이 용어의 사용이 리프팅이 의미하는 것에 대한 직관적이고 좋은 지침 이라는 것을 알았습니다 . 서로 다른 상황 사이에 존재하는 유일한 차이점은이 높은 추상화가 실제로 무엇인지입니다.
특히, Viktor는 함수형 프로그래밍의 맥락에서 알려져 있으며,이 맥락에서 리프팅에 대한 시각적으로 다른 해석을 찾을 수 있습니다 . 예를 들어, 값을 functor로 올리거나 모나드 값 (예 : Haskell 's liftM2
) 에서 작동하는 함수를 들어 올리는 것 입니다.
"리프트 표현"의 매우 구체적인 예는 f.ex. List(1)
또는 이어야합니다 Some(1)
.
이러한 종류의 개념은 일반적으로 구체적인 예를 통해 이해하기가 가장 쉽습니다. 이 Flow API 예제 에서 발췌 한 다음을 고려하십시오 .
Flow(text.split("\\s").toVector).
// transform
map(line => line.toUpperCase).
// print to console (can also use ``foreach(println)``)
foreach(transformedLine => println(transformedLine)).
onComplete(FlowMaterializer(MaterializerSettings())) {
case Success(_) => system.shutdown()
case Failure(e) =>
println("Failure: " + e.getMessage)
system.shutdown()
}
다음 코드가 필요합니다.
text.split("\\s").toVector.
map(line => line.toUpperCase).
foreach(println)
그리고 그것을 Flow
문맥 으로 "들어 올립니다" . 이를 통해 알고리즘을 지정하는 데 익숙한 것과 동일한 구문을 사용할 수 있지만, map
여러 프로세서 또는 기계에서 병렬로 수행 된 후 foreach(println)
해당 출력을 하나의 프로세서로 매끄럽게 수집하여 인쇄합니다.
이것은 모든 유형의 컨텍스트를 감싸는 것을 의미하는 일반적인 용어입니다. 보다 친숙한 또 다른 예는 map
단일 요소에서 작동하고 해당 요소 컬렉션에서 작업하는 새로운 컨텍스트로 "리프팅"하는 함수를 사용하는 것입니다. 리프팅은 함수형 프로그래밍에서 보편적으로 사용되며 함수형 코드를 재사용하는 것이 훨씬 쉬운 주된 이유 중 하나입니다.