2010-10-05 21 views
5

Estaba leyendo un tutorial de Haskell (Learn You a Haskell) en el que el autor dijo que la pereza va bien con la transparencia referencial. Después de leer más y buscar algo, todavía no entiendo por qué. Tenga en cuenta que entiendo lo bueno de la transparencia referencial y la pereza, pero son ellos los que me preocupan.¿Por qué la pereza va bien con la transparencia referencial?

¿Hay algún beneficio especial de la combinación de los dos?

O tal vez el autor solo quería decir que ambos son agradables de tener y expresó eso ambiguamente?

Respuesta

11

Es realmente fácil. Una evaluación no estricta (por ejemplo, floja) significa que las tareas pueden posponerse. Pero para posponer algo, está más seguro de que obtendrá más tarde el mismo resultado que obtendría ahora, y eso es transparencia referencial. Considere este código Java imperativo:

long start = System.currentTimeMillis(); //get the start time 
runBenchmarkFunction(); 
System.out.println("Run took " + (System.currentTimeMillis() - start) + " ms"); 

Ahora un lenguaje vago sería posponer la evaluación de los productos de la primera línea, ya que sólo es necesario inicio en la tercera línea. Entonces el resultado sería 0 (o muy cercano). Probablemente eso no es lo que quieres. La razón de ese problema sería que System.currentTimeMillis es no referencial transparente. No tendría ningún problema en ese caso si fuera una función en el "sentido matemático" como sin o ln, que es referencial transparente.

+1

"el estado solo es necesario en la tercera línea". Esto no es estrictamente cierto. El efecto secundario de haber pedido al sistema la hora actual es necesario para ejecutar la segunda línea; es del tipo 'IO a', no' a'. runBenchmarkFunction es del tipo similar, y para ejecutar ambos, debes combinarlos con alguna función que asegure que las acciones se ejecutan en orden, '>>' en Haskell. Entonces realmente estás escribiendo 'currentTime >> = \ st -> runBenchmarkFunction >> currentTime >> = \ end -> putStrLn" tardó "++ (show $ end - st) ++" seconds "'. Claramente, la segunda línea depende de la primera, por lo que todo funciona. – jrockway

+0

@jrockway: Estoy usando aquí un lenguaje ficticio que podría llamar "Java perezoso" como un ejemplo muy crudo y fácil de explicar la conexión entre la pereza y la transparencia referencial. Cómo se resuelve el problema en Haskell es una ** pregunta ** completamente diferente. Tenga en cuenta que el "modo de la mónada" de Haskell no es la única posibilidad, p. Clean usa su sistema de tipos para lidiar con este problema. – Landei

+1

La pregunta está etiquetada con "haskell". Pero aún así, lo que has escrito es perfectamente referencialmente transparente si imaginas la semántica correcta. Y, si imaginas otra semántica, entonces no lo es. Pero la palabra clave allí es "imaginar". – jrockway

5

La transparencia referencial significa que la función siempre devolverá el mismo resultado con la misma entrada. Entonces, si no importa si la función es floja o estricta. La función diferida calculará su salida en algún momento desconocido en el futuro, pero debido a la transparencia referencial se le garantiza que la salida será siempre la misma para las entradas dadas.

De alguna manera, la transparencia referencial asegura la corrección de las funciones perezosas.

4

Considere este código de Python, donde se usa un generador para calcular perezosamente una secuencia infinita. No tiene transparencia referencial debido a su uso del estado global, por lo tanto, una persona que llama del generador no puede estar segura de que el resultado que obtiene no haya sido afectado por algún otro evento.

foo = 0 

def foo_sequence(): 
    global foo 
    while True: 
     foo += 1 
     yield foo 

>>> generator = foo_sequence() 
>>> generator.next() 
1 
>>> generator.next() 
2 
>>> foo = 5 
>>> generator.next() 
6 

En este caso, la persona que llama preferiría generar la secuencia completa de forma atómica, para evitar que ocurran dichos eventos. Por lo tanto, la falta de transparencia referencial (en este ejemplo artificial) hace que la pereza sea poco atractiva.

+0

Muy buen ejemplo.Por supuesto, también es posible romper la transparencia referencial en Haskell, aunque generalmente hay señales de advertencia en el camino. –

+0

@John: ¿Quieres decir con el uso de cosas primitivas o 'insafePerformIO'? Estos se consideran dañinos si no se usan adecuadamente. No puedo imaginar otra forma. – fuz

+0

@FUZxxl, eso es exactamente lo que quiero decir, y el prefijo 'inseguro' sería la advertencia. Otra forma es ajustar un puntero a ByteString y luego modificar el puntero. –

Cuestiones relacionadas