ここでこの用語に出くわしました:
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
関数はfunctionを受け取り、A => B
何らかの方法でマジックを実行して、持ち上げられた関数F[A] => F[B]
をファンクターまたはモナドに適用できるようにしF[A]
ます。
Scalaの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
こうして私たちは、これらの値のリストの抽象化を使用することができ、インスタンス。
モナドは、水密でありながら構成可能なインターフェースを提供することにより、何らかのタイプの内部動作をカプセル化することを可能にします。リフト表現を使用すると、計算について推論するのが簡単になります。このような抽象化の使用は、抽象化された詳細の知識を失うことも意味しますが、それらは内部で効率的な実装を提供するために必要です(適切な実行表現を見つける)。
+
ように定義された演算子があるとしますint + int --> int
。null可能リフト演算子int? + int? --> int?
のセマンティクスは、「どちらかのオペランドがnullの場合、答えはnullです。それ以外の場合は、値に非リフト演算子を使用します」。
A
B
F
F
が型コンストラクタである場合F[A]
、その構築型の1つです。それでは、なぜこれら4つのタイプについて話すのは間違っているのでしょうか?(もちろん、2つの型と1つの型のコンストラクターでも同じようにうまく
もちろん、持ち上げるという用語は、文脈に応じて異なる意味を持つことができます。
では、一般的なプログラミングは次のより高いレベルに抽象化のプロセスについて説明します。たとえば、2つのコードを使用できます。1つはを使用し、もう1つint
はを使用しfloat
ます。このコードをリフティングするということT
は、int
との両方で機能するジェネリック型でメソッドをテンプレート化するようなことを意味しfloat
ます。
この用語の使用は、リフティングの意味についての直観的な優れたガイドラインであることがわかりました。異なるコンテキスト間に存在すると思われる唯一の違いは、このより高い抽象化が実際に何であるかです。
特に、Viktorは関数型プログラミングのコンテキストで知られていますが、このコンテキストでは、リフティングの視覚的に異なる解釈を見つけることができます。1つの例は、値をファンクターに持ち上げるか、関数を持ち上げて単項値(つまりHaskellの値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)
出力を1つのプロセッサーにシームレスに収集して印刷します。
これは、あらゆるタイプのコンテキストをラップすることを指す一般的な用語です。もう1つのより身近な例はmap
、単一の要素で機能する関数を使用して、それらの要素のコレクションで作業するという新しいコンテキストに「持ち上げ」ます。リフティングは関数型プログラミングで広く使用されており、関数型コードの再利用が非常に簡単な主な理由の1つです。