haskell - ¿Qué significa "reificar" y "reificar" en el contexto de la programación(funcional?).
functional-programming metaprogramming (6)
Así que leí sobre esto, y es más o menos lo que significa: tomar un concepto abstracto y hacerlo concreto. O bien, hay un proxy que representa el concepto abstracto. Por ejemplo, en Lisp, el concepto de abstracción y aplicación de procedimientos se reifica cuando se usa lambdas.
La reificación en sí misma es un concepto amplio y no solo aplicable a los lenguajes de programación funcionales.
En Java, por ejemplo, hay tipos que están disponibles en tiempo de ejecución. Estos son tipos reificables. Es decir, existe una representación concreta del concepto abstracto del tipo, durante el tiempo de ejecución. Por el contrario, hay tipos no reificables. Esto es especialmente evidente durante el uso de genéricos en Java. En Java, los genéricos están sujetos a borrado de tipo, por lo que la información de tipo genérica no está disponible durante el tiempo de ejecución (a menos que el tipo parametrizado utilice comodines ilimitados).
Otro ejemplo es cuando intentas modelar un concepto. Por ejemplo, supongamos que tiene una clase Group
y una clase User
. Ahora hay ciertos conceptos abstractos que describen la relación entre los dos. Por ejemplo, el concepto abstracto de un User
como miembro de un Group
. Para hacer que esta relación sea concreta, escribiría un método llamado isMemberOf
que dice si un User
es miembro de un Group
. Entonces, lo que has hecho aquí es que has reificado (hecho real / explícito / concreto) el concepto abstracto de membresía grupal.
Otro buen ejemplo es una base de datos donde tiene relaciones padre-hijo entre objetos. Puedes describir esta relación en el concepto abstracto de un árbol. Ahora supongamos que tiene una función / método que toma estos datos de la base de datos y construye un objeto Tree
real . Lo que has hecho ahora es reificar el concepto abstracto de la relación parecida a un Tree
padre-hijo en un objeto Tree
real .
Volviendo a los lenguajes funcionales en general, quizás el mejor ejemplo de reificación es la creación del propio lenguaje de programación Lisp. Lisp era una construcción completamente abstracta y teórica (básicamente solo una notación matemática para lenguajes de computadora). Siguió siendo así hasta que Steve Russel implementó realmente la función de eval
de Lisp en un IBM 704:
De acuerdo con lo informado por Paul Graham en Hackers & Painters, p. 185, McCarthy dijo: "Steve Russell dijo, mira, ¿por qué no programo esta evaluación ..., y le dije, ho, ho, estás confundiendo la teoría con la práctica, esta evaluación es para leer, no para computación. Pero siguió adelante y lo hizo. Es decir, compiló la evaluación en mi documento en el código de máquina IBM 704, corrigió errores, y luego publicitó esto como un intérprete de Lisp, que sin duda era así. Entonces, en ese momento, Lisp tenía esencialmente la forma que tiene hoy ... "
Así que Lisp se reificó a partir de un concepto abstracto, en un lenguaje de programación real.
Leí mucho este término en blogs sobre haskell y programación funcional (especialmente en el blog de sigfpe ) pero no tengo ni idea de lo que significa. Me salgo con la suya sin saberlo la mayoría de las veces, pero probablemente hubiera entendido los textos mucho mejor si lo supiera. Google no me ayudó. Me pierdo en lo técnico.
También el significado no técnico del mundo ("convertir lo abstracto en abstracto") no me ayuda a entender lo que significa prácticamente reificar algo en el código.
Soy un poco lento con los conceptos de informática, por lo que los ejemplos prácticos con código serían agradables. :PAG
De la Wiki Haskell :
"Reificar" algo es tomar algo que es abstracto y considerarlo material. Un ejemplo clásico es la forma en que los antiguos tomaron conceptos abstractos (por ejemplo, "victoria") y los convirtieron en deidades (por ejemplo, Nike, la diosa griega de la victoria).
Un tipo reificado es un valor que representa un tipo. El uso de tipos reificados en lugar de tipos reales significa que puede hacer cualquier manipulación con ellos que pueda hacer con los valores.
Incluso solo en el contexto de Haskell, el término se usa de manera muy amplia. El paquete reify de Andy Gill le permite tomar estructuras recursivas y convertirlas en gráficos explícitos. La publicación de Sigpfe sobre las continuaciones describe la reificación de la noción de "el resto de la computación" en un valor que puede pasar. Plantilla Haskell tiene una función de reificación (ejecutada, junto con el código TH en general, en tiempo de compilación) que cuando se le da el nombre de un valor Haskell devuelve información disponible sobre él (donde se declara, escribe, etc.).
¿Qué tienen todos estos casos en común? Están hablando de tomar algo que podemos razonar y saber, pero que no podemos manipular directamente mediante programación, y convertirlo en un valor real de primera clase que podemos nombrar y transmitir como cualquier otro. Y esa es generalmente la intención que las personas quieren transmitir cuando usan la palabra.
Sé que existe el concepto de reificación en RDF. Como dijo Tim Bernes-Lee :
La reificación en este contexto significa la expresión de algo en un idioma que usa el lenguaje, de modo que sea tratable por el lenguaje.
Supongo que es una especie de reflexión o introspección. ¡Espero que obtengas algunas buenas respuestas aquí!
Un uso en el que puedo pensar (¡estoy seguro de que hay otros!) Está convirtiendo una clase en un diccionario. Tomemos la clase Eq
(olvidando el operador /=
por el momento):
class Eq a where
(==) :: a -> a -> Bool
Si reificamos esta clase, se convierte en:
data EqDict a = EqDict (a -> a -> Bool)
que se puede construir, inspeccionar, etc. También es digno de mención que solo puede tener una instancia Eq
por tipo, pero múltiples valores EqDict
. Pero la construcción automática de instancias (por ejemplo, obtener igualdad para las listas cuando la tiene para los elementos) no funciona; tendrás que construir el valor de EqDict [a]
tú mismo.
El proceso de reificación es tan simple como esto (para este caso):
reify :: Eq a => EqDict a
reify = EqDict (==)
Una función que utiliza la clase Eq
podría transformar algo como esto:
-- silly example, doesn''t really do anything
findMatches :: Eq a => a -> [a] -> [a]
findMatches x ys = [ y | y <- ys, x == y ]
-- version using EqDict
findMatchesDict :: EqDict a -> a -> [a] -> [a]
findMatchesDict (EqDict f) x ys = [ y | y <- ys, f x y ]
Si desenvuelve el EqDict y acaba de pasar un a -> a -> Bool
, obtendrá las funciones ..By
, como Data.List.nubBy
y amigos - un truco similar para Ord
lleva a Data.List.sortBy
.
Cosificación
La reificación es una forma de instanciación. Cuando reifica un concepto, toma algo abstracto y lo concreta, al igual que la definición del diccionario que proporcionó.
Puede optar por reificar un tipo como un término que habita un árbol de sintaxis abstracta de tipos posibles.
Puede reificar un patrón de diseño al idear una implementación de propósito general para algún idioma. Por ejemplo, algo así como
template<typename T> class Singleton {
public:
static T& Instance() {
static T me;
return me;
}
protected:
virtual ~Singleton() {};
Singleton() {};
}
reifica el patrón de diseño singleton como una plantilla en C ++.
Puede reificar la idea de Hoare de quicksort en una implementación en el lenguaje de programación de su elección. En este sentido, dedico mucho tiempo a reificar los conceptos de la teoría de categorías en el código Haskell.
Puede reificar un idioma como intérprete para ese idioma. La idea de Larry Wall de Perl el lenguaje se reifica como el intérprete de Perl.
Los paquetes de verificación de data-reify y vacuum reifican los términos como gráficos que representan cómo se estructura en la memoria con el intercambio.
Reflexión
La otra cara de la reificación es la reflexión , que toma algo concreto, y genera una abstracción, generalmente al olvidar algunos detalles. Tal vez quieras hacer esto porque la abstracción es más simple, o de alguna manera captura la esencia de lo que estás hablando.
La reflexión del sistema de tipos en Java, C #, etc. toma una clase concreta en un lenguaje de programación y le proporciona una estructura de la estructura abstracta, que le da acceso a la lista de miembros que proporcionan sus clases. Aquí tomamos la noción concreta de un tipo y generamos un término abstracto que describe su estructura, descartando cualquier valor particular.
Al igual que cómo puede reificar un lenguaje de programación en una implementación, algunas veces puede ir en la dirección opuesta. Aunque esto generalmente se considera una mala idea, puede tomar una implementación e intentar reflejar una especificación de idioma a partir de las propiedades deseables de su comportamiento. TeX fue implementado primero por Knuth, sans specification. Cualquier especificación de TeX se ha reflejado en la implementación de Knuth.
(Más formalmente si ves la reflexión como un funcionador olvidadizo que te lleva de un dominio concreto a un dominio abstracto, entonces la reificación es, idealmente, dejada adjunta a la reflexión).
El paquete de reflection que mantengo proporciona un método de revisión que toma un término y arroja un tipo que lo representa, luego un método de reflexión que le permite generar un nuevo término. Aquí el dominio ''concreto'' es el sistema de tipo, y el dominio abstracto son términos.