2012-07-13 12 views
13

tengo la siguiente función:¿Cómo conseguir el valor normal de la acción IO en Haskell

get :: Chars -> IO Chars 
get cs = do 
    char <- getChar 
    let (dats, idx) = (curData cs, curIndex cs) 
    let (x,y:xs) = splitAt idx dats 
    let replacement = x ++ (ord char) : xs 
    return $ Chars replacement idx 

y estoy deseando conseguir un Chars fuera de él, no una acción IO. Tengo no idea de cómo hacer esto, o si es posible.

Chars es básicamente un contenedor con un [Int] llamado curData y un Int llamado curIndex. Los detalles no son tan importantes, solo quiero saber si hay una forma para que esta función devuelva un Chars en lugar de un IO Chars.

Si no, ¿cómo paso esto como argumento a una función que toma un Chars? Soy algo nuevo para Haskell IO, pero no creo que quiera que todas mis funciones tomen Chars como argumentos para tener que tomar IO Chars como argumentos, y luego extraerlos y volver a empaquetarlos. Parece innecesario

Gracias!

+5

¿no tenemos una canónica "¿Cómo consigo un' a '' fuera de un a' IO?"pregunta para marcar esto como un duplicado de? –

+8

Aquí hay demasiadas respuestas informativas, y no hay suficientes fotos de gatos lindos. Así que lo dejaré aquí: http://spl.smugmug.com/Humor/Lambdacats/ trapd-in-IO-monad-plz-help/960526421_MnNqB-S-1.jpg – rtperson

Respuesta

18

No se puede, porque eso violaría referential transparency.

IO en Haskell se hace exactamente para distinguir entre acciones cuyos resultados y efectos pueden variar dependiendo de la interacción con el entorno/usuario y funciones puras cuyos resultados no van a cambiar cuando los llames con los mismos parámetros de entrada .

Con el fin de pasar el resultado a una pura función de tomar una Chars de entrada que tiene que llamar a su acción IO en otra acción IO, unir el resultado con el operador <- a una variable y pasarlo a su función pura. Pseudocódigo ejemplo:

myPureFunction :: Chars -> ... 

otherAction :: Chars -> IO() 
otherAction cs = do 
    myChars <- get cs 
    let pureResult = myPureFunction myChars 
    ... 

Si eres nuevo en IO en Haskell, puede que desee echar un vistazo a los capítulos de entrada y salida en Learn You a Haskell for a Great Good! y Real World Haskell.

En realidad, hay una forma de obtener un valor puro de una acción IO, pero en su caso no debería hacerlo, ya que está interactuando con el medio ambiente: la forma insegura está bien solo cuando puede garantizar que no está violando la transparencia referencial.

+0

Agregué referencias a capítulos de libros sobre IO. –

+0

Gracias! Creo que esto tiene sentido ahora. He leído todo LYAH, pero es Ha pasado un tiempo desde que hice algo con IO, así que no estaba seguro de cómo manejarlo. Entonces, tengo algunas funciones que toman 'Chars' y devuelven' Chars' pero no tocan IO ¿Debería modificar esos para devolver un 'IO Chars' solo en aras de la simplicidad? Tengo dudas de cambiar todo de esa manera, pero el programa debería funcionar teóricamente dado que ese es el caso. –

+1

No, no deberías dar hasta en transparencia referencial garantizado por el tipo s cuando puedes Entonces, dejen que esas funciones sean, no les hagan regresar algo como 'IO a'. –

8

Es imposible (miento, hay una manera extremadamente insegura de engañar para salir de allí).

El punto es que si se realiza alguna E/S, el comportamiento y el resultado de su programa pueden no depender solo de argumentos explícitos para las funciones utilizadas, por lo que debe declararse en el tipo con IO something.

utiliza el resultado de una acción IO a en una pura función uniéndose el resultado en main (o algo que se llama a partir main) y luego aplicar la función pura, vinculante el resultado en un let,

cs ::Chars 
cs = undefined 

main = do 
    chars <- get cs 
    let result = pureFunction chars 
    print result 

o, si la función que desea aplicar a chars tiene tipo Chars -> IO b

main = do 
    chars <- get cs 
    doSomething chars 
+0

Sólo una nota realmente menor: en tus ejemplos, su función 'get' debería tomar' Chars'. –

+0

Gracias, lo perdí. –

+0

De nada;) –