¿Qué es una "representación elevada"?

12

Acabo de encontrar este término aquí:

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

"Mostraremos la API de Flow, una representación levantada, así como una forma conectable de transformar la representación levantada en la representación de ejecución: Materialización de flujo".

Buscar en Google no ayudó mucho.

Guarida
fuente
lectura recomendada: Discuta esto $ {blog}
mosquito
11
@gnat parece que no inventó ese término, no parece una opinión, no es probable que provoque una discusión y mi intuición es que no va a ser demasiado amplio (aunque parece matemático).
Den
2
Discuto el significado de "levantado" en el contexto de C # aquí: blogs.msdn.com/b/ericlippert/archive/2007/06/27/… - probablemente los desarrolladores de Scala están usando el término de forma análoga, pero más moda general.
Eric Lippert

Respuestas:

22

No estoy familiarizado con la API de Flow.

El término "levantamiento" proviene de la teoría de categorías. En lenguajes de programación como Haskell o Scala, una liftfunción toma una función A => By de alguna manera realiza magia para que la función elevada F[A] => F[B]pueda aplicarse a un functor o mónada F[A].

Un ejemplo concreto con el Seqcontenedor de Scala : supongamos que tenemos una función def double(x: Int): Int = 2 * xy una secuencia val xs = Seq(1, 2, 3). No podemos double(xs)debido a tipos incompatibles. Pero si obtenemos a val doubleSeq = liftToSeq(double), podemos hacer doubleSeq(xs), lo que se evalúa como Seq(2, 4, 6). Aquí, liftToSeqse puede implementar como

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

El Seq(…)constructor también puede verse como una operación de elevación, que eleva los valores 1, 2, 3a una Seqinstancia, lo que nos permite usar abstracciones de lista para estos valores.

Las mónadas nos permiten encapsular el funcionamiento interno de algún tipo al ofrecer una interfaz hermética pero componible. El uso de una representación elevada puede facilitar el razonamiento sobre un cálculo. El uso de tales abstracciones también significa que perdemos el conocimiento de los detalles abstractos, pero son necesarios para proporcionar una implementación eficiente bajo el capó (encontrar una representación de ejecución adecuada).

amon
fuente
44
Esa es una buena descripción del "levantamiento" matemático. También deberíamos incluir una referencia a la descripción más formal del levantamiento de Wikipedia .
Scott Whitlock
3
Un ejemplo quizás más claro de "elevación" es la elevación a tipos anulables (u "opcionales" o "quizás"). Por ejemplo, suponga que tiene un operador +definido de tal manera int + int --> int. El operador elevado a anulable int? + int? --> int?tiene la semántica de "si cualquiera de los operandos es nulo, la respuesta es nula; de lo contrario, utilice el operador no elevado en los valores".
Eric Lippert
@ScottWhitlock ¿Incluso levantas?
helrich
1
@ Frank Leí el artículo de Wikipedia antes de escribir mi respuesta, y tampoco lo entendí. En cambio, encontré que el Wiki de Haskell sobre Lifting es más accesible. Tenga en cuenta que realmente no tenemos cuatro tipos. Tenemos cuatro tipos concretos, pero solo tres variables de tipo: dos tipos Ay B, y un functor Fque es un constructor de tipos.
amon
1
No estoy demasiado metido en todo esto, pero si Fes un constructor de tipos, entonces F[A]es uno de sus tipos construidos. Entonces, ¿por qué está mal hablar de estos cuatro tipos? (dos tipos y un constructor de tipos serían igualmente buenos, por supuesto)
Frank
6

El término para levantar puede, por supuesto, tener diferentes significados según el contexto.

En la programación genérica , describe el proceso de abstracción al siguiente nivel superior. Por ejemplo, podría tener dos piezas de código, una con inty la otra con float. Levantar este código significaría algo así como crear una plantilla del método con un tipo genérico Tque funcione para ambos, inty float.

Este uso del término me pareció una buena guía intuitiva para lo que significa levantar objetos. La única diferencia que parece existir entre los diferentes contextos es lo que realmente es esta abstracción superior.

En particular, Viktor es conocido en el contexto de la programación funcional, y en este contexto, puede encontrar interpretaciones visualmente diferentes de levantar allí. Un ejemplo es elevar valores a un functor, o elevar funciones para trabajar en valores monádicos (es decir, Haskell liftM2).

Un ejemplo muy concreto de una "representación elevada" podría entonces f.ex. ser una List(1), o un Some(1).

Franco
fuente
4

Este tipo de conceptos son generalmente más fáciles de entender con un ejemplo concreto. Considere el siguiente extracto de este ejemplo de 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()
      }

Esto toma el siguiente código:

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

y lo "eleva" a un Flowcontexto. Eso le permite usar la misma sintaxis con la que está familiarizado para especificar su algoritmo, pero detrás de escena mapse realiza en paralelo en varios procesadores o incluso máquinas, y luego foreach(println)recolecta sin problemas esa salida a un procesador para imprimir.

Este es un término genérico que puede referirse a envolver cualquier contexto alrededor de cualquier tipo. Otro ejemplo más familiar es maptomar una función que funciona en un solo elemento y la "eleva" al nuevo contexto de trabajo en una colección de esos elementos. Lifting es omnipresente en la programación funcional y una de las principales razones por las que es mucho más fácil reutilizar el código funcional.

Karl Bielefeldt
fuente