Подтвердить что ты не робот

Преобразование IO Int в Int

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

4b9b3361

Ответ 1

Как правило, вы пишете что-то вроде этого:

do
   x <- somethingThatReturnsIO
   somethingElseThatReturnsIO $ pureFunction x

Невозможно получить "Int" из "IO Int" , кроме как сделать что-то еще в IO Monad.

В монадных терминах указанный код помещает в

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

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

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

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

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

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

Ответ 2

Ну, есть 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

Чтобы понять, что эти типы - шаг за шагом, сначала посмотрите, что такое Maybe and List:

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

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

Список (a) s может быть записан как ( [] a) и как ( [a]). Примерами значений ( [Int]) являются [1,7,42] и [].

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

Теперь тип comboBoxGetActive:

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

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

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