2010-11-20 1 views
12

Я создал combobox из преобразования xmlWidget в comboBox с функцией castTocomboBox и теперь хочу получить текст или индекс активного элемента. Проблема в том, что если я использую функцию comboBoxGetActive, она возвращает результат IO Int, и мне нужно знать, как я могу получить значение Int. Я попытался прочитать о монадах, чтобы понять, что можно сделать в такой ситуации, но я, похоже, не понимаю. Я ценю всю помощь, которую я могу получить. Вероятно, я должен упомянуть, что использую Glade и gtk2hs.Преобразование IO Int в Int

+8

Возможный дубликат функции [Haskell типа: IO String-> String] (http://stackoverflow.com/questions/1675366/a-haskell-function-of-type-io-string-string). –

ответ

27

По общему правилу вы пишете что-то вроде этого:

do 
    x <- somethingThatReturnsIO 
    somethingElseThatReturnsIO $ pureFunction x 

Там нет никакого способа, чтобы получить «Int» из-за «IO Int», за исключением того, чтобы сделать что-то еще в IO Монады.

В монадных терминах, приведенный выше код desugars в

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

В ">> =" оператор (произносится "привязывать") делает волшебство преобразования "IO Int" в "Int", но он отказывается отдать это Int прямо вам. Он передаст это значение только в другую функцию в качестве аргумента, и эта функция должна вернуть другое значение в «IO». Медитируйте на типе привязки для монады IO в течение нескольких минут, и вы можете быть просветленным:

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

Первый аргументом является вашим первоначальным «IO Int» значение, что «comboBoxGetActive» возвращается. Вторая - это функция, которая принимает значение Int и превращает его в другое значение IO. Таким образом, вы можете обрабатывать Int, но результаты этого никогда не убегают от монады IO.

(Конечно, есть пресловутый «unsafePerformIO», но на вашем уровне знаний вы можете быть уверены, что если вы используете его, то вы делаете это неправильно.)

(На самом деле desugaring несколько сложнее ., чтобы обеспечить не удалось совпадения паттерн Но вы можете делать вид, что я верно написал)

+1

Привет, Пол, я в настоящее время пытаюсь использовать случайные инты из System.random для ints, но это не так. Есть ли вероятность, что вы можете мне помочь? Я поставил код на pastebin на день: [link] (http://pastebin.com/1s3bNztY) –

+0

Ваша проблема в том, что вы не можете иметь истинные случайные числа в чистом вычислении: это то, что означает ваши ошибки типа. Поэтому вам нужно посмотреть на чистые функции, такие как randomR, которые принимают генератор и возвращают случайный результат и новый генератор. Вы берете возвращаемый генератор и используете его для следующего случайного значения. Ваша функция должна принимать и возвращать генератор так же, как randomR. Затем вызовите вашу чистую функцию с помощью getStdRandom на верхнем уровне. Взгляните на источник «randoms» для некоторых подсказок. Кстати, вы считали, что произойдет, если ваш список случайных чисел имеет одинаковое число в два раза? –

+0

Привет, Паул, пока не думал об этом. Можете ли вы, может быть, дать мне простую реализацию? Я не могу понять это с генератором. –

11

Ну, есть unsafePerformIO: http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/System-IO-Unsafe.html#v:unsafePerformIO

(Если вы хотите знать, как найти этот метод: Перейти к http://www.haskell.org/hoogle и искать подписи вам нужно, здесь IO a -> a)

, что сказал, вы, вероятно, слышал о том, «что происходит в IO, остается в IO». И есть очень веские причины для этого (просто прочитайте документацию небезопасногоPerformIO). Поэтому у вас, скорее всего, есть проблема с дизайном, но для того, чтобы получить помощь от опытных Haskellers (я, конечно же, нет), вам нужно более подробно описать вашу проблему.

+3

@downvoter: Не могли бы вы объяснить? Я думаю, что мой ответ верен: я объяснил, как вы могли бы сделать то, что было задано, и что это, скорее всего, плохая идея. – Landei

3

чтобы понять, что эти типы -ступенно от Step-, первый посмотреть, что может быть, и список являются:

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

(Возможно,) отличается от (a), например (Возможно, Int) отличается от (Int). Примеры значений типа (Может быть Int) не Только 5 и Ничто.

Перечень () с может быть записана в виде ([] к производному), и как ([а]). Примеры значений ([Int]): [1,7,42] и [].

Теперь, ап (IO) это другое дело, чем (), также: Это Input/Output-вычисления, который вычисляет значение типа (). Другими словами: это скрипт или программа, которая должна быть выполнена для генерации значения типа (a). Пример (IO String) is getLine, который считывает строку текста со стандартного ввода.

Теперь тип comboBoxGetActive является:

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

Это означает, что comboBoxGetActive функция (->), переводящий из любого типа, который имеет экземпляр типа класса ComboBoxClass (примитив типы классов как-то похожи на java-интерфейсы) на (IO Int). Каждый раз эта функция (->) оценивается с тем же входным значением этого типа (self) (независимо от того, какой тип), это приводит к тому же значению: всегда одно и то же значение типа (IO Int), это означает, что это всегда один и тот же сценарий. Но когда вы выполняете тот же скрипт в разное время, он может создавать разные значения типа (Int).

Основная функция вашей программы имеет тип (IO()), это означает, что компилятор и исполняющая система оценки уравнений, которые вы программируете в этом функциональном языке к стоимости основной, который будет выполнен как только вы запустите программу.

 Смежные вопросы

  • Нет связанных вопросов^_^