Что такое «поднятое представление»?

12

Просто наткнулся на этот термин здесь:

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

«Мы продемонстрируем Flow API - поднятое представление - а также подключаемый способ преобразования поднятого представления в представление выполнения - Flow Materialization».

Поиск в Google не сильно помог.

логово
источник
рекомендуемое чтение: Обсудите этот $ {blog}
gnat
11
@Nat кажется, что он не придумал этот термин, это не похоже на мнение, это не может спровоцировать дискуссию, и мое интуитивное ощущение, что он не будет слишком широким (хотя кажется, что математика).
День
2
Я обсуждаю значение «поднял» в контексте C # здесь: blogs.msdn.com/b/ericlippert/archive/2007/06/27/… - вероятно, разработчики Scala используют этот термин в аналогичном, но более общая мода.
Эрик Липперт

Ответы:

22

Я не знаком с API Flow.

Термин «подъем» происходит от теории категорий. В таких языках программирования, как Haskell или Scala, liftфункция берет функцию A => Bи каким-то образом выполняет магию, чтобы поднятую функцию F[A] => F[B]можно было применить к функтору или монаде F[A].

Конкретный пример с использованием Seqконтейнера Scala . Предположим, у нас есть функция def double(x: Int): Int = 2 * xи последовательность 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случае, что позволяет нам использовать список абстракций для этих значений.

Монады позволяют нам инкапсулировать внутреннюю работу некоторого типа, предлагая водонепроницаемый, но составной интерфейс. Использование поднятого представления может облегчить рассуждение о вычислении. Использование таких абстракций также означает, что мы теряем знание об абстрагированных особенностях, но они необходимы для обеспечения эффективной реализации под капотом (поиск подходящего представления исполнения).

Амон
источник
4
Это хорошее описание математического «подъема». Мы также должны включить ссылку на более формальное описание подъема из Википедии .
Скотт Уитлок
3
Возможно, более ясный пример «поднятия» - это поднятия до обнуляемых (или «необязательных» или «возможно») типов. Например, предположим, у вас есть оператор, +определенный так, что int + int --> int. Оператор с поднятым-обнуляемым значением int? + int? --> int?имеет семантику «если любой операнд равен нулю, тогда ответ равен нулю, в противном случае используйте оператор без поднятых значений».
Эрик Липперт
@ ScottWhitlock Ты вообще поднимаешь?
Хелрих
1
@Frank Я прочитал статью в Википедии, прежде чем написать свой ответ, и тоже не понял. Вместо этого я обнаружил, что Wiki Haskell по лифтингу более доступно. Обратите внимание, что у нас на самом деле нет четырех типов. У нас есть четыре конкретных типа, но только три типа переменных: два типа Aи B, и функтор, Fкоторый является конструктором типов.
Амон
1
Я не слишком глубоко во всем этом, но если Fэто конструктор типа, то F[A]это один из его созданных типов. Так почему неправильно говорить об этих четырех типах? (два типа и один конструктор типов будут одинаково хороши, конечно)
Фрэнк
6

Термин « поднять» может, конечно, иметь разные значения в зависимости от контекста.

В общем программировании он описывает процесс абстрагирования на следующий более высокий уровень. Например, у вас может быть два фрагмента кода, один с типом int, а другой с float. Отмена этого кода будет означать что-то вроде шаблонизации метода с универсальным типом, Tкоторый работает как для, так intи для float.

Я нашел это использование термина, чтобы быть хорошим интуитивным руководством для того, что означает подъем . Единственное различие, которое, кажется, существует между различными контекстами, состоит в том, чем на самом деле является эта более высокая абстракция.

В частности, Виктор известен в контексте функционального программирования, и в этом контексте вы можете найти совершенно разные интерпретации подъема . Один из примеров - поднять значения в функтор или поднять функции для работы с монадическими значениями (например, Haskell liftM2).

Очень конкретный пример «поднятого представления» может быть, например, быть List(1), или Some(1).

Фрэнк
источник
4

Подобные концепции обычно легче всего понять на конкретном примере. Рассмотрим следующую выдержку из этого примера 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использование функции, работающей с одним элементом, и «поднятие» ее в новый контекст работы с коллекцией этих элементов. Лифтинг повсеместен в функциональном программировании и является одной из основных причин, по которой намного проще повторно использовать функциональный код.

Карл Билефельдт
источник