2010-01-28 5 views

Respuesta

33

¿Qué alternativas existen a mónadas de E/S en un lenguaje funcional puro?

Soy consciente de dos alternativas en la literatura:

  • Uno de ellos es el llamado sistema de tipo lineal . La idea es que un valor de tipo lineal debe usarse exactamente una vez: no puede ignorarlo, y no puede usarlo dos veces. Con esta idea en mente, le da al estado del mundo un tipo abstracto (por ejemplo, World), y lo hace lineal. Si me marca tipos lineales con una estrella, entonces aquí son los tipos de algunas operaciones de E/S:

    getChar :: World* -> (Char, World*) 
    putChar :: Char -> World* -> World* 
    

    y así sucesivamente. El compilador se asegura de que nunca copies el mundo, y luego puede organizar la compilación del código que actualiza el mundo en su lugar, lo cual es seguro porque solo hay una copia.

    La exclusividad de tipeo en el lenguaje Clean se basa en la linealidad.

    Este sistema tiene un par de ventajas; en particular, no impone el orden total en los eventos que hacen las mónadas. También tiende a evitar el "IO sin bin" que se ve en Haskell donde todos los cómputos efectivos se lanzan en la mónada IO y todos se ordenan totalmente si desea un pedido total o no.

  • El otro sistema que soy consciente de las mónadas es anterior y limpio y se basa en la idea de que un programa interactivo es una función de una secuencia (posiblemente infinito) de solicitudes a una secuencia (posiblemente infinita) de respuestas. Este sistema, que se llamaba "diálogos", era un infierno para programar. Nadie lo extraña, y no tenía nada en particular para recomendarlo. Sus fallas se enumeran muy bien en the paper that introduced monadic I/O (Imperative Functional Programming) por Wadler y Peyton Jones. Este documento también menciona un sistema de E/S basado en continuaciones que fue presentado por el grupo Yale Haskell pero que fue efímero.

+1

La secuenciación a través de la unión de la mónada es más o menos el estilo de continuación y paso de verificación de tipo de todos modos, ¿no? Mi impresión fue que las mónadas y las continuaciones son en su mayoría intercambiables, excepto que las continuas decididamente no son, en general, cálidas * o * borrosas. –

+2

Las continuas forman una mónada, pero las mónadas son decididamente * no * continuación. CPS es mucho más poderoso porque puedes hacer copias de cosas (¡incluidas las continuas!). Las mónadas restringen las cosas mucho más severamente que la mera verificación de tipos. –

+0

"Las mónadas definitivamente no son continuaciones", no, pero la relación no es solo una instancia de una. Cf. http://lambda-the-ultimate.org/node/3235 Lawvere Theories and Monads, Hyland & Power, 2007. –

4

tipificación Singularidad se utiliza en Clean

5

Si por "pura" que quiere decir "referencialmente transparente", es decir, que una función aplicada es libremente intercambiable con su resultado evaluadas (y, por tanto, que llama a una función con el mismo argumentos tiene el mismo resultado cada vez), cualquier concepto de IO con estado se excluye por definición.

Hay dos estrategias en bruto que yo sepa:

  • Vamos hago una función IO, pero asegúrese de que nunca se puede llamar dos veces con los mismos argumentos exactos; esto da un paso al frente al dejar que las funciones sean trivialmente "referencialmente transparentes".

  • Trate el programa completo como una función pura simple tomando como argumento todas las entradas recibidas y devolviendo "todas las salidas producidas", con ambas representadas por alguna forma de flujo diferido para permitir la interactividad.

Hay una variedad de maneras de implementar ambos enfoques, así como un cierto grado de solapamiento - por ejemplo, en el segundo caso, las funciones que operan en el I/es improbable que se llama dos veces con el S corrientes la misma parte de la corriente. Qué forma de verlo tenga más sentido depende del tipo de soporte que el lenguaje le brinde.

En Haskell, IO es un tipo de mónada que se enrosca automáticamente estado secuencial a través del código (similar a la funcionalmente puro State mónada), de tal manera que, conceptualmente, cada llamada a una función de otro modo impuro consigue un valor diferente de la implícita "estado del mundo exterior".

El otro enfoque popular que conozco utiliza algo así como linear types con un final similar; asegurando que las funciones impuras nunca obtengan los mismos argumentos dos veces al tener valores que no pueden copiarse o duplicarse, de modo que los viejos valores del "estado del mundo exterior" no puedan mantenerse y reutilizarse.

5

Imperative Functional Programming por Peyton Jones y Wadler es una lectura obligada si le interesa la IO funcional. Los otros enfoques que se discuten son:

  • diálogos que son corrientes de descanso de las respuestas y peticiones

type Dialogue = [Response] -> [Request]

main :: Dialogue

  • continuaciones - cada operación IO toma una continuación como argumento

  • Tipos lineales: el sistema de tipos lo restringe de una manera que no puede copiar o destruir el estado externo, lo que significa que no puede llamar a una función dos veces con el mismo estado.

3

Functional Reactive Programming es otra forma de manejar esto.

+1

Nunca escuché el término "Programación reactiva de funciones". ¿Puedes cambiarlo a "Programación funcional reactiva"? Gran respuesta de lo contrario. –

+0

No hay problema, gracias por notarlo. No tengo idea de cómo lo escribí mal. –

Cuestiones relacionadas