Co to jest „zniesiona reprezentacja”?

12

Właśnie natknąłem się na ten termin tutaj:

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

„Zaprezentujemy Flow API - zniesioną reprezentację - a także możliwy do podłączenia sposób przekształcenia zniesionej reprezentacji w reprezentację wykonawczą - Flow Materialization”.

Googling niewiele pomógł.

Legowisko
źródło
zalecana lektura: Porozmawiaj o tym {blog}
gnat
11
@gnat wydaje się, że nie wymyślił tego terminu, nie wygląda na opinię, raczej nie wywoła dyskusji, a moje przeczucie jest takie, że nie będzie ono zbyt szerokie (choć wydaje się matematyczne).
Den
2
Omawiam znaczenie „podniesiony” w kontekście C # tutaj: blogs.msdn.com/b/ericlippert/archive/2007/06/27/... - prawdopodobnie twórcy Scali używają tego terminu w analogiczny sposób, ale więcej ogólna moda.
Eric Lippert,

Odpowiedzi:

22

Nie znam interfejsu API Flow.

Termin „podnoszenie” pochodzi od teorii kategorii. W językach programowania, takich jak Haskell lub Scala, liftfunkcja przyjmuje funkcję A => Bi w jakiś sposób wykonuje magię, dzięki czemu podniesioną funkcję F[A] => F[B]można zastosować do funktora lub monady F[A].

Konkretny przykład z wykorzystaniem Seqkontenera Scali : Załóżmy, że mamy funkcję def double(x: Int): Int = 2 * xi sekwencję val xs = Seq(1, 2, 3). Nie możemy z double(xs)powodu niezgodnych typów. Ale jeśli otrzymamy val doubleSeq = liftToSeq(double), możemy to zrobić doubleSeq(xs), co ocenia Seq(2, 4, 6). Tutaj liftToSeqmożna zaimplementować jako

def liftToSeq[A, B](f: A => B): (Seq[A] => Seq[B]) =
  (seq: Seq[A]) => seq.map(f)

Seq(…)Konstruktor może być również postrzegane jako operacja podnoszenia, który podnosi wartość 1, 2, 3na Seqprzykład, co pozwala nam korzystać z list abstrakcje dla tych wartości.

Monady pozwalają nam enkapsulować wewnętrzne działania pewnego rodzaju, oferując wodoszczelny, ale łatwy do skomponowania interfejs. Zastosowanie podniesionej reprezentacji może ułatwić uzasadnienie obliczeń. Korzystanie z takich abstrakcji oznacza również, że tracimy wiedzę na temat abstrakcji, ale są one potrzebne do zapewnienia efektywnej implementacji pod maską (znalezienie odpowiedniej reprezentacji wykonania).

amon
źródło
4
To dobry opis matematycznego „podnoszenia”. Powinniśmy również zamieścić odniesienie do bardziej formalnego opisu podnoszenia z Wikipedii .
Scott Whitlock,
3
Być może bardziej wyraźnym przykładem „podnoszenia” jest podnoszenie na typy zerowalne (lub „opcjonalne” lub „może”). Załóżmy na przykład, że masz operatora +zdefiniowanego w taki sposób int + int --> int. Operator podniesiony do int? + int? --> int?pustego ma semantykę „jeśli którykolwiek operand ma wartość zerową, wówczas odpowiedź jest pusta, w przeciwnym razie użyj operatora nie podniesionego do wartości”.
Eric Lippert,
@ScottWhitlock Czy w ogóle podnosisz?
helrich
1
@Frank Przeczytałem artykuł w Wikipedii przed napisaniem mojej odpowiedzi i też jej nie zrozumiałem. Zamiast tego, znalazłem się Haskell Wiki na podnoszenia się bardziej dostępne. Pamiętaj, że tak naprawdę nie mamy czterech typów. Mamy cztery konkretne typy, ale tylko trzy zmienne typu: dwa typy Ai Boraz funktor, Fktóry jest konstruktorem typów.
amon
1
Nie jestem zbyt głęboko w to wszystko, ale jeśli Fjest konstruktorem typów, to F[A]jest jednym z jego typów. Dlaczego więc źle jest mówić o tych czterech typach? (dwa typy i jeden typ konstruktora byłyby oczywiście równie dobre)
Frank
6

Termin „ podnoszenie” może oczywiście mieć różne znaczenie w zależności od kontekstu.

W programowaniu ogólnym opisuje proces abstrakcji do następnego wyższego poziomu. Na przykład, możesz mieć dwa fragmenty kodu, jeden typ z int, a drugi z float. Zniesienie tego kodu oznaczałoby coś w rodzaju szablonowania metody za pomocą ogólnego typu, Tktóry działa zarówno dla, jak inti float.

Uznałem, że użycie tego terminu jest dobrą intuicyjną wytyczną dotyczącą tego, co oznacza podnoszenie . Jedyna różnica, jaka wydaje się istnieć między różnymi kontekstami, polega na tym, czym tak naprawdę jest ta wyższa abstrakcja.

W szczególności Viktor jest znany w kontekście programowania funkcjonalnego, aw tym kontekście można znaleźć wyraźnie różne interpretacje podnoszenia . Jednym z przykładów jest podniesienie wartości do funktora lub podniesienie funkcji do pracy na wartościach monadycznych (tj. Haskella liftM2).

Bardzo konkretny przykład „zniesionej reprezentacji” mógłby np. Np. być List(1)albo Some(1).

Szczery
źródło
4

Tego rodzaju pojęcia są zazwyczaj najłatwiejsze do zrozumienia na konkretnym przykładzie. Rozważ następujący fragment tego przykładu interfejsu API Flow :

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()
      }

To wymaga następującego kodu:

text.split("\\s").toVector.
      map(line => line.toUpperCase).
      foreach(println)

i „podnosi” to w Flowkontekście. Pozwala to na użycie tej samej składni, którą znasz do określania algorytmu, ale za kulisami mapodbywa się to równolegle na kilku procesorach, a nawet na maszynach, a następnie foreach(println)płynnie zbiera dane wyjściowe z powrotem do jednego procesora w celu drukowania.

Jest to ogólny termin, który może odnosić się do zawijania dowolnego kontekstu wokół dowolnego typu. Innym bardziej znanym przykładem jest mapfunkcja, która działa na jednym elemencie i „przenosi” go w nowy kontekst pracy nad kolekcją tych elementów. Podnoszenie jest wszechobecne w programowaniu funkcjonalnym i jednym z głównych powodów o wiele łatwiejszego ponownego wykorzystania kodu funkcjonalnego.

Karl Bielefeldt
źródło