2012-07-13 17 views
13

Ho la seguente funzione:Come ottenere il valore normale da azioni IO in 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 

e sto volendo ottenere un Chars fuori di esso, non un'azione IO. Ho no idea di come farlo, o se è anche possibile.

Chars è fondamentalmente solo un contenitore con un [Int] chiamato curData e un Int chiamato curIndex. Le specifiche non sono così importanti, voglio solo sapere se c'è un modo per questa funzione di restituire un Chars invece di un IO Chars.

In caso negativo, come si passa questo argomento come argomento a una funzione che accetta uno Chars? Sono un po 'nuovo a Haskell IO, ma non credo di volere che tutte le mie funzioni richiedano Chars come argomenti per prendere invece gli argomenti come IO Chars e quindi estrarli e riconfezionarli. Sembra inutile.

Grazie!

+5

non abbiamo forse una canonica "Come faccio ad avere un' a' di un iO a' '?"domanda per contrassegnare questo duplicato di ancora? –

+8

Ci sono troppe risposte informative qui, e non abbastanza foto di gatti carini. Quindi lascerò questo qui: http://spl.smugmug.com/Humor/Lambdacats/ trapd-in-IO-monad-plz-help/960526421_MnNqB-S-1.jpg – rtperson

risposta

18

Non è possibile, perché ciò violerebbe referential transparency.

IO in Haskell è stato creato in questo modo esattamente per distinguere tra azioni il cui risultato e gli effetti possono variare a seconda dell'interazione con l'ambiente/utente e le funzioni pure i cui risultati non cambieranno quando li si chiama con gli stessi parametri di input .

Al fine di passare il risultato a una pura funzione di prendere una Chars in ingresso è necessario chiamare la vostra azione IO in un'altra azione IO, associare il risultato con l'operatore <- a una variabile e passarlo alla funzione pura. Esempio Pseudocodice:

myPureFunction :: Chars -> ... 

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

Se siete nuovi a IO in Haskell, si potrebbe desiderare di avere uno sguardo ai capitoli ingresso e di uscita in Learn You a Haskell for a Great Good! e Real World Haskell.

C'è in realtà un modo per ottenere semplicemente un valore puro da un'azione IO, ma nel tuo caso non dovresti farlo, come stai interagendo con l'ambiente: il modo pericoloso è ok solo quando puoi garantisci che non stai violando la trasparenza referenziale.

+0

Ho aggiunto riferimenti ai capitoli di libri su IO. –

+0

Grazie! Penso che questo abbia senso ora. Ho letto tutto di LYAH, ma è è passato un po 'di tempo da quando ho fatto qualsiasi cosa con IO quindi non ero sicuro di come gestirlo. Quindi, ho alcune funzioni che prendono un 'Chars' e restituiscono un' Chars' ma non toccano IO Devo modificare quelli per restituire un 'IO Chars 'solo per semplicità? Sono riluttante a cambiare tutto in questo modo, ma il programma dovrebbe teoricamente funzionare ancora dato che è il caso –

+1

No, non dovresti dare sulla trasparenza referenziale garantita dal tipo s quando puoi. Quindi lascia che siano quelle funzioni, non farle restituire qualcosa come "IO a". –

8

È impossibile (mentire, c'è un modo estremamente pericoloso per imbrogliarvi fuori).

Il punto è che se viene eseguito un I/O, il comportamento e il risultato del programma potrebbero non dipendere solo da argomenti espliciti per le funzioni utilizzate, quindi è necessario dichiararlo nel tipo facendolo IO something.

si utilizza il risultato di un IO a azione in una pura funzione legando il risultato in main (o qualcosa chiamato da main) e poi applicare la funzione pura, vincolante il risultato in un let,

cs ::Chars 
cs = undefined 

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

oppure, se la funzione che si desidera applicare a chars è digitare Chars -> IO b

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

Solo una nota davvero piccola: nei tuoi esempi, la sua funzione 'get' dovrebbe prendere un' Chars'. –

+0

Grazie, mancato. –

+0

Prego;) –