Converting IO Int to Int

22,209

Solution 1

As a general rule you write something like this:

do
   x <- somethingThatReturnsIO
   somethingElseThatReturnsIO $ pureFunction x

There is no way to get the "Int" out of an "IO Int", except to do something else in the IO Monad.

In monad terms, the above code desugars into

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

The ">>=" operator (pronounced "bind") does the magic of converting the "IO Int" into an "Int", but it refuses to give that Int straight to you. It will only pass that value into another function as an argument, and that function must return another value in "IO". Meditate on the type of bind for the IO monad for a few minutes, and you may be enlightened:

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

The first argument is your initial "IO Int" value that "comboBoxGetActive" is returning. The second is a function that takes the Int value and turns it into some other IO value. Thus you can process the Int, but the results of doing so never escape from the IO monad.

(Of course there is the infamous "unsafePerformIO", but at your level of knowledge you may be certain that if you use it then you are doing it wrong.)

(Actually the desugaring is rather more complicated to allow for failed pattern matches. But you can pretend what I wrote is true)

Solution 2

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

(If you want to know how to find this method: Go to http://www.haskell.org/hoogle and search for the signature you need, here IO a -> a)

That said, you probably heard of "What happens in IO stays in IO". And there are very good reasons for this (just read the documentation of unsafePerformIO). So you very likely have a design problem, but in order to get help from experienced Haskellers (I'm certainly not), you need to describe your problem more detailed.

Solution 3

To understand what those types are –step by step–, first look up what Maybe and List are:

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

(Maybe a) is a different type than (a), like (Maybe Int) differs from (Int). Example values of the type (Maybe Int) are Just 5 and Nothing.

A List of (a)s can be written as ([ ] a) and as ([a]). Example values of ([Int]) are [1,7,42] and [ ].

Now, an (IO a) is a different thing than (a), too: It is an Input/Output-computation that calculates a value of type (a). In other words: it is a script or program, which has to be executed to generate a value of type (a). An Example of (IO String) is getLine, which reads a line of text from standard-input.

Now, the type of comboBoxGetActive is:

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

That means, that comboBoxGetActive is a function (->) that maps from any type that has an instance of the type-class ComboBoxClass (primitive type-classes are somehow similar to java-interfaces) to an (IO Int). Each time, this function (->) is evaluated with the same input value of this type (self) (whatever that type is), it results in the same value: It is always the same value of type (IO Int), that means that it is always the same script. But when you execute that same script at different times, it could produce different values of type (Int).

The main function of your program has the type (IO ()), that means that the compiler and the runtime system evaluate the equations that you program in this functional language to the value of main, which will be executed as soon as you start the program.

Share:
22,209

Related videos on Youtube

izayoi
Author by

izayoi

Updated on July 09, 2022

Comments

  • izayoi
    izayoi almost 2 years

    I've created a combobox from converting a xmlWidget to a comboBox with the function castTocomboBox and now I want to get the text or the index of the active item. The problem is that if I use the comboBoxGetActive function it returns an IO Int result and I need to know how can I obtain the Int value. I tried to read about monads so I could understand what one could do in a situation like this but I don't seem to understand. I appreciate all the help I can get. I should probably mention that I use Glade and gtk2hs.

  • Landei
    Landei over 13 years
    @downvoter: Would you please explain? I think my answer is correct: I explained how you could do what was asked, and that it's very likely a bad idea.
  • Karl-John Chow
    Karl-John Chow over 9 years
    Hi Paul, I am currently trying to cast random Ints from System.random to ints but It doesn't go well. Is there a possibility that you can help me? I put the code on pastebin for a day: link
  • Paul Johnson
    Paul Johnson over 9 years
    Your problem is that you cannot have true random numbers in a pure computation: that is what your type errors mean. So you need to look at pure functions like randomR which take a generator and return a random result and a new generator. You take the returned generator and use that for your next random value. Your function needs to take and return a generator just like randomR. Then call your pure function with getStdRandom at the top level. Take a look at the source of "randoms" for some clues. BTW, have you considered what happens if your list of random numbers has the same number twice?
  • Karl-John Chow
    Karl-John Chow over 9 years
    Hi paul, didnt thought about that yet. Can you maybe give me a simple implementation? I can't figure it out with the generator.
  • Paul Johnson
    Paul Johnson over 9 years
    Your type signature should be "makeIntSet:: Int -> [Int] -> StdGen -> (Set Int, StdGen)". Compare this to the type of the first argument of GetStdRandom