2010-11-20 18 views
12

He creado un cuadro combinado de la conversión de un xmlWidget a un comboBox con la función castTocomboBox y ahora quiero obtener el texto o el índice del elemento activo. El problema es que si uso la función comboBoxGetActive, devuelve un resultado IO Int y necesito saber cómo puedo obtener el valor Int. Intenté leer acerca de las mónadas para poder entender qué se podía hacer en una situación como esta, pero parece que no lo entiendo. Agradezco toda la ayuda que puedo obtener. Probablemente debería mencionar que utilizo Glade y gtk2hs.conversión de IO Int a Int

+8

Posible duplicado de [Una función de tipo Haskell: IO String-> String] (http://stackoverflow.com/questions/1675366/a-haskell-function-of-type-io-string-string). –

Respuesta

27

Como regla general se escribe así:

do 
    x <- somethingThatReturnsIO 
    somethingElseThatReturnsIO $ pureFunction x 

No hay manera de conseguir el "Int" de un "IO Int", salvo que hacer algo más en el IO Mónada.

En términos Mónada, el código de seguridad desugars en

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

El ">> =" operador (pronunciado "bind") hace la magia de convertir el "IO Int" en una "Int", pero se niega a darte ese Int directamente. Solo pasará ese valor a otra función como argumento, y esa función debe devolver otro valor en "IO". Medite en el tipo de vinculación para la mónada IO durante unos minutos, y que sean iluminados:

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

El primer argumento es el valor inicial "IO Int" que "comboBoxGetActive" está regresando. La segunda es una función que toma el valor Int y lo convierte en algún otro valor de IO. Por lo tanto, puede procesar el Int, pero los resultados de hacerlo nunca escapan de la mónada IO.

(Por supuesto que es el famoso "unsafePerformIO", pero a su nivel de conocimiento que puede estar seguro de que si lo usa, entonces usted está haciendo mal.)

(En realidad, el desugaring es bastante más complicado . para permitir fallado patrón coincide Pero se puede pretender que lo que escribí es verdad)

+1

Hola, Paul, actualmente estoy intentando lanzar Ints aleatorios de System.random a Ints, pero no va bien. ¿Hay alguna posibilidad de que puedas ayudarme? Puse el código en pastebin por un día: [link] (http://pastebin.com/1s3bNztY) –

+0

Su problema es que no puede tener números aleatorios verdaderos en un cálculo puro: eso es lo que significan los errores de tipo. Por lo tanto, debe observar funciones puras como randomR, que toman un generador y arrojan un resultado aleatorio y un nuevo generador. Toma el generador devuelto y lo usa para su próximo valor aleatorio. Su función necesita tomar y devolver un generador como randomR. Luego llame a su función pura con getStdRandom en el nivel superior. Eche un vistazo a la fuente de "randoms" para algunas pistas. Por cierto, ¿has considerado lo que sucede si tu lista de números aleatorios tiene el mismo número dos veces? –

+0

Hola paul, aún no había pensado en eso. ¿Puede darme una implementación simple? No puedo resolverlo con el generador. –

11

Bueno, hay unsafePerformIO: http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/System-IO-Unsafe.html#v:unsafePerformIO

(Si desea saber cómo encontrar este método: Ir a http://www.haskell.org/hoogle y la búsqueda de la firma que necesita, aquí IO a -> a)

Dicho esto, es probable que oído hablar de "Lo que sucede en IO permanece en IO". Y hay muy buenas razones para esto (solo lea la documentación de inseguroPerformIO). Entonces es muy probable que tengas un problema de diseño, pero para poder obtener ayuda de Haskellers con experiencia (ciertamente no), necesitas describir tu problema más detalladamente.

+3

@downvoter: ¿Podrías explicarme? Creo que mi respuesta es correcta: le expliqué cómo podría hacer lo que se le preguntó, y que es muy probable que sea una mala idea. – Landei

3

para entender lo que esos tipos son -paso por paso-, primero buscar lo mejor y la lista son:

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

(Quizás un) es un tipo diferente (a), como (Maybe Int) difiere de (Int). Los valores de ejemplo del tipo (Maybe Int) son Solo 5 y Nothing.

A Lista de (un) s se puede escribir como ([] a) y como ([a]). Los valores de ejemplo de ([Int]) son [1,7,42] y [].

Ahora, un (IO un) es una cosa diferente que (un), también: Es un/salida-entrada de cálculo que calcula un valor de tipo (un). En otras palabras: es un script o programa, que debe ejecutarse para generar un valor de tipo (a). Un ejemplo de (IO String) es getLine, que lee una línea de texto de una entrada estándar.

Ahora, el tipo de comboBoxGetActive es:

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

Eso significa, que comboBoxGetActive es una función (->) que mapea de cualquier tipo que tiene una instancia de la clase de tipo ComboBoxClass (primitiva type-classes son de alguna manera similares a las interfaces java) a un (IO Int). Cada vez, esta función (->) se evalúa con el mismo valor de entrada de este tipo (auto) (cualquiera que sea ese tipo), da como resultado el mismo valor: siempre es el mismo valor de tipo (IO Int), eso significa que siempre es el mismo script. Pero cuando ejecuta ese mismo script en diferentes momentos, puede producir diferentes valores de tipo (Int).

La función principal de su programa tiene el tipo (IO()), que significa que el compilador y el sistema de ejecución evalúan las ecuaciones que programa en este lenguaje funcional al valor del principal, que se ejecutarán tan pronto como comience el programa.