2010-11-20 18 views
12

Ho creato una casella combinata dalla conversione di xmlWidget a comboBox con la funzione castTocomboBox e ora voglio ottenere il testo o l'indice dell'elemento attivo. Il problema è che se uso la funzione comboBoxGetActive restituisce un risultato IO Int e ho bisogno di sapere come posso ottenere il valore Int. Ho provato a leggere le monadi, così ho potuto capire cosa si poteva fare in una situazione come questa, ma non mi sembra di capire. Apprezzo tutto l'aiuto che posso ottenere. Probabilmente dovrei dire che io uso Glade e gtk2hs.Conversione da IO Int a Int

+8

Possibile duplicato di [una funzione Haskell di tipo: stringa IO-> stringa] (http://stackoverflow.com/questions/1675366/a-haskell-function-of-type-io-string-string). –

risposta

27

Come regola generale si scrive qualcosa di simile:

do 
    x <- somethingThatReturnsIO 
    somethingElseThatReturnsIO $ pureFunction x 

Non v'è alcun modo per ottenere il "Int" fuori da un "IO Int", se non per fare qualcosa di diverso nella IO Monade.

In termini monade, il codice sopra desugars in

somethingThatReturnsIO >>= (\x -> somethingElseThatReturnsIO $ pureFunction x) 

L'operatore ">> =" (pronunciato "legare") fa la magia di conversione del "IO Int" in un "Int", ma si rifiuta di dare quella Int direttamente a te. Passerà solo quel valore in un'altra funzione come argomento e tale funzione deve restituire un altro valore in "IO". Meditare sul tipo di bind per la monade IO per pochi minuti, e si può essere illuminati:

>>= :: IO a -> (a -> IO b) -> IO b 

Il primo argomento è il vostro valore iniziale "IO Int" che "comboBoxGetActive" sta tornando. Il secondo è una funzione che prende il valore Int e lo trasforma in un altro valore di I/O. In questo modo è possibile elaborare l'Int, ma i risultati di tale operazione non sfuggono mai alla monade IO.

(Naturalmente c'è il famigerato "unsafePerformIO", ma al tuo livello di conoscenza si può essere certi che se lo si utilizza allora si sta facendo male.)

(In realtà il Dezuccheraggio è un po 'più complicata . per consentire la riuscita modello corrisponde Ma si può far finta di quello che ho scritto è vero)

+1

Ciao Paolo, Attualmente sto cercando di lanciare Ints casuali da System.Random a interi, ma non va bene. C'è una possibilità che tu possa aiutarmi? Ho messo il codice su pastebin per un giorno: [link] (http://pastebin.com/1s3bNztY) –

+0

Il tuo problema è che non si può avere veri numeri casuali in un calcolo puro: questo è ciò che significano i vostri errori di tipo. Quindi è necessario esaminare le funzioni pure come randomR che prendono un generatore e restituiscono un risultato casuale e un nuovo generatore. Prendi il generatore restituito e lo usi per il tuo prossimo valore casuale. La tua funzione deve prendere e restituire un generatore come randomR. Quindi chiama la tua funzione pura con getStdRandom al livello più alto. Dai un'occhiata alla fonte dei "randoms" per alcuni indizi. A proposito, hai considerato cosa succede se la tua lista di numeri casuali ha lo stesso numero due volte? –

+0

Ciao Paul, non ci avevo ancora pensato. Puoi darmi una semplice implementazione? Non riesco a capirlo con il generatore. –

11

Beh, c'è unsafePerformIO: http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/System-IO-Unsafe.html#v:unsafePerformIO

(Se volete sapere come trovare questo metodo: Vai http://www.haskell.org/hoogle e cercare la firma è necessario, qui IO a -> a)

Detto questo, probabilmente sentito parlare di "Cosa succede in IO rimane in IO". E ci sono molto buoni motivi per questo (basta leggere la documentazione di unsafePerformIO). Quindi molto probabilmente hai un problema di progettazione, ma per ottenere aiuto dagli esperti Haskellers (non lo sono certamente), devi descrivere il tuo problema in modo più dettagliato.

+3

@downvoter: spiegheresti per favore? Penso che la mia risposta sia corretta: ho spiegato come potresti fare ciò che è stato chiesto e che è molto probabilmente una cattiva idea. – Landei

3

per capire che cosa questi tipi sono -step da passo-, primo sguardo a ciò che forse e lista sono:

data Maybe a = Nothing | Just a 
data [a]  = [] | a : [a] 

(Forse a) è un tipo diverso (un), come (Forse Int) differisce da (Int). valori esempio del tipo (Forse Int) sono soli 5 e Niente.

una lista di (un) s può essere scritta come ([] un) e come ([a]). I valori di esempio di ([Int]) sono [1,7,42] e [].

Ora, un (IO un) è una cosa diversa rispetto (un), troppo: Si tratta di un/Output-calcolo di ingresso che calcola un valore di tipo (un). In altre parole: è uno script o un programma, che deve essere eseguito per generare un valore di tipo (a). Un esempio di (stringa IO) è getLine, che legge una riga di testo dallo standard input.

Ora, il tipo di comboBoxGetActive è:

comboBoxGetActive :: ComboBoxClass self => self -> IO Int 

Ciò significa, che comboBoxGetActive è una funzione (->) che mappa da qualsiasi tipo che ha un esempio del tipo di classe ComboBoxClass (primitiva le classi di tipi sono in qualche modo simili alle interfacce java) a un (IO Int). Ogni volta, questa funzione (->) viene valutata con lo stesso valore di input di questo tipo (self) (qualunque sia il tipo specificato), restituisce lo stesso valore: È sempre lo stesso valore di tipo (IO Int), ciò significa che è sempre lo stesso script. Ma quando si esegue lo stesso script in momenti diversi, potrebbe produrre valori diversi di tipo (Int).

La funzione principale del programma presenta il tipo (IO()), ciò significa che il compilatore e il sistema runtime valutano le equazioni che si programma in questo linguaggio funzionale al valore della principale, che verranno eseguiti non appena si avvia il programma.