「リフト表現」とは何ですか?


12

ここでこの用語に出くわしました:

http://www.codemesh.io/codemesh2014/viktor-klang

「リフトされた表現であるFlow APIと、リフトされた表現を実行表現に変換するプラグ可能な方法であるFlow Materializationのデモを行います。」

グーグルはあまり役に立ちませんでした。



11
@gnat彼はその用語を発明しなかったようです、それは意見のように見えません、それは議論を引き起こす可能性は低く、私の直感はそれがあまりにも広すぎないということです(数学のように感じますが)。
デン14

2
C#のコンテキストでの「リフト」の意味については、blogs.msdn.com / b / ericlippert / archive / 2007/06/27 / ...で説明します。おそらく、Scala開発者はこの用語を似たような形で使用していますが、一般的なファッション。
エリックリッパー14

回答:


22

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, 3Seqこうして私たちは、これらの値のリストの抽象化を使用することができ、インスタンス。

モナドは、水密でありながら構成可能なインターフェースを提供することにより、何らかのタイプの内部動作をカプセル化することを可能にします。リフト表現を使用すると、計算について推論するのが簡単になります。このような抽象化の使用は、抽象化された詳細の知識を失うことも意味しますが、それらは内部で効率的な実装を提供するために必要です(適切な実行表現を見つける)。


4
それは数学的な「リフティング」の良い説明です。ウィキペディアからのリフティングのより正式な説明への参照も含める必要があります。
スコットホイットロック

3
「リフティング」のおそらくより明確な例は、null許容(または「オプション」または「多分」)タイプへのリフティングです。たとえば、の+ように定義された演算子があるとしますint + int --> int。null可能リフト演算子int? + int? --> int?のセマンティクスは、「どちらかのオペランドがnullの場合、答えはnullです。それ以外の場合は、値に非リフト演算子を使用します」。
エリックリッパー14

@ScottWhitlockあなたも持ち上げますか?
ヘルリッチ14

1
@Frank答えを書く前にウィキペディアの記事を読みましたが、それも理解できませんでした。その代わり、私が見つかりましたHaskellのウィキをリフティングよりアクセスできるようにします。実際には4つのタイプはありません。4つの具象型がありますが、型変数は3つだけです。2つの型と、および型コンストラクターであるファンクターです。ABF
アモン14

1
私はこれのすべてに深くはありませんが、if Fが型コンストラクタである場合F[A]、その構築型の1つです。それでは、なぜこれら4つのタイプについて話すのは間違っているのでしょうか?(もちろん、2つの型と1つの型のコンストラクターでも同じようにうまく
フランク14

6

もちろん、持ち上げるという用語は、文脈に応じて異なる意味を持つことができます。

では、一般的なプログラミングは次のより高いレベルに抽象化のプロセスについて説明します。たとえば、2つのコードを使用できます。1つはを使用し、もう1つintはを使用しfloatます。このコードをリフティングするということTは、intとの両方で機能するジェネリック型でメソッドをテンプレート化するようなことを意味しfloatます。

この用語の使用は、リフティングの意味についての直観的な優れたガイドラインであることがわかりました。異なるコンテキスト間に存在すると思われる唯一の違いは、このより高い抽象化が実際に何であるかです。

特に、Viktorは関数型プログラミングのコンテキストで知られていますが、このコンテキストでは、リフティングの視覚的に異なる解釈を見つけることができます。1つの例は、値をファンクターに持ち上げるか、関数を持ち上げて単項値(つまりHaskellの値liftM2)を処理することです。

「持ち上げられた表現」の非常に具体的な例は、f.ex。ことList(1)、またはSome(1)


4

これらの種類の概念は、通常、具体的な例を使用して理解するのが最も簡単です。この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つです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.