2010-10-03 10 views

Respuesta

18

Hay dos técnicas que son utilizadas por los lenguajes de programación puramente funcionales para modelar los efectos secundarios:

1) Un tipo de mundo que representa el estado externo, donde cada valor de ese tipo está garantizada por el sistema de tipo para ser utilizado sólo una vez.

En un idioma que utiliza este enfoque y la función printread podría tener los tipos (string, world) -> world y world -> (string, world) respectivamente.

Podrían ser utilizados como esto:

let main w = 
    let w1 = print ("What's your name?", w) in 
    let (str, w2) = read w1 in 
    let w3 = print ("Your name is "^name, w2) in 
    w3 

Pero no les gusta esto:

let main w = 
    let w1 = print ("What's your name?", w) in 
    let (str, w2) = read w in 
    let w3 = print ("Your name is "^name, w2) in 
    w3 

(debido w se usa dos veces)

Todas las funciones integradas con efectos secundarios tomaría y devolvería un valor mundial. Como todas las funciones con efectos secundarios están integradas o llaman a otras funciones con efectos secundarios, esto significa que todas las funciones con efectos secundarios deben tomar y devolver un mundo.

De esta manera, no es posible llamar a una función con efectos secundarios dos veces con los mismos argumentos y no se infringe la transparencia referencial.

2) Una món IO donde todas las operaciones con efectos secundarios tienen que ejecutarse dentro de esa mónada.

Con este enfoque, todas las operaciones con efectos secundarios tendrían el tipo io something. Por ejemplo print sería una función con tipo string -> io unit y read tendría el tipo io string.

La única manera de acceder al valor de realizar una operación sería usar la operación "monadic bind" (llamada >> = en haskell por ejemplo) con la operación IO como un argumento y una función que describe qué hacer con el resultado como el otro operando.

El ejemplo anterior quedaría así con monádico IO:

let main = 
    (print "What's your name?") >>= 
    (lambda() -> read >>= 
    (lambda name -> print ("Your name is "^name))) 
+4

Your # 2 es un detalle de implementación para su # 1. La mónada IO simplemente transportaría automáticamente ese estado mundial para usted, empaquetándolo y desempaqueándolo según sea necesario detrás de la sintaxis que use su mónada. –

+1

@JUST: ¿Quiere decir que # 1 es un detalle de implementación de # 2, no? Pero luego no es un detalle de implementación si se trata de la interfaz expuesta al programador. – sepp2k

+0

Sí, claro. Lo siento. # 1 es un detalle de implementación de # 2. –

1

Según mi entender, si quiere tener efectos secundarios en un lenguaje funcional, debe codificarlos explícitamente.

11

Hay varias opciones disponibles para manejar E/S en un lenguaje funcional.

  • Do not be pure. Muchos lenguajes funcionales no son puramente funcionales. Es más que admite programación funcional en lugar de aplicarla. Esta es, de lejos, la solución más común al problema de E/S en la programación funcional. (Ejemplos: Lisp, Scheme, ML estándar, Erlang, etc.)
  • Transformación de flujo. La E/S Early Haskell se hizo de esta manera. Revise mi enlace a continuación para obtener más detalles si desea más información. (Sugerencia: es probable que no.)
  • I/O de continuación de la continuación (el "paso del mundo" mencionado en otras respuestas). En este pasa un token de datos con su E/S que actúa como el "valor diferente" necesario para mantener viva la integridad referencial . Esto es utilizado por varios dialectos ML si la memoria sirve.
  • La palabra "continuación" o "mundo" de arriba puede ser envuelta en varios tipos de datos, el más (en) famoso siendo el uso de mónadas en este rol en Haskell. Tenga en cuenta que esto es, teóricamente, lo mismo en las cubiertas, pero se elimina el tedio de realizar un seguimiento de las variables de estado "mundial"/"continuación".

Hay a research dissertation que analiza estos exhaustivamente.

La E/S funcional es un campo de investigación en curso y hay otros lenguajes que abordan este problema de maneras interesantes y desquiciantes. Hoare logic se usa en algunos idiomas de investigación. Otros (como Mercury) usan uniqueness typing. Otros (como Clean) usan effect systems. De estos, tengo una exposición muy, muy limitada a Mercury solamente, así que realmente no puedo comentar sobre los detalles. Hay un paper que detalla el sistema de E/S de Clean en profundidad, sin embargo, si está interesado en esa dirección.

Cuestiones relacionadas