Проблема при отображении целочисленной арифметики со случайным числом в Haskell - PullRequest
2 голосов
/ 12 августа 2011

Допустим, я хочу создать случайное число в Haskell.Для этого я использую

randomRIO (0, 10)

, который генерирует для меня число от 0 до 10.Это тип

randomRIO (0,10) :: (Random a, Num a) => IO a

Теперь, допустим, я присваиваю его результат значению k.Это тип IO Integer.

Попытка выполнить обычную арифметическую работу, такую ​​как k + 2, даст следующий результат в Ghci:

<interactive>:1:3:
    No instance for (Num (IO Integer))
      arising from the literal `2'
    Possible fix: add an instance declaration for (Num (IO Integer))
    In the second argument of `(+)', namely `2'
    In the expression: k + 2
    In an equation for `it': it = k + 2

Проблема также возникает при попытке задать Ghci

[randomRIO (0, 10) | x <- [0..10]]

Сообщение об ошибке немного загадочно, как я могу использовать случайные числа в Haskell?

Ответы [ 3 ]

10 голосов
/ 12 августа 2011

Значение типа IO Integer не является целым числом. Это действие, которое при выполнении возвращает целое число. Различие важно. Единственный способ выполнить IO действия - подключить их к main или ввести их в GHCi.

То есть randomRIO (0, 10) - это действие, которое при выполнении возвращает случайное число от 0 до 10. Обратите внимание, что это , а не функция, поскольку функция всегда должна возвращать один и тот же результат при одном и том же входном сигнале, хотя мы иногда называем это нечистая функция .

Итак, вопрос в том, как выполнить действие, возвращающее целое число, и выполнить действие, возвращающее целое число плюс два? Легко, вы можете использовать fmap, чтобы объединить действие и чистую функцию, превращая его результат в новое действие.

fmap (+2) $ randomRIO (0, 10)

Control.Monad содержит много полезных функций для создания новых действий из других действий. Для вашего второго примера мы можем использовать replicateM, который создает действие, которое при выполнении запускает исходное действие несколько раз, собирая результаты в список:

replicateM 10 $ randomRIO (0, 10)

Вы также можете получить аналогичные результаты вручную, используя do -notation.

Для получения дополнительной информации вам следует прочитать монады, например, в Learn You a Haskell .

4 голосов
/ 12 августа 2011

Лучше всего вам будет работать через такой ресурс, как Learn You a Haskell .Очень актуальный раздел - здесь .

3 голосов
/ 12 августа 2011

Поскольку вы упомянули GHCi, обратите внимание, что вы также можете выполнять действия ввода-вывода в приглашении и связать значение из действия с именем, используя <-.

a <- randomRIO (0, 10)
a + 2

Однако я предлагаю вам прочитатьчерез учебник, который связал Энтони и Хаммар.Он объяснит приведенный выше синтаксис (и другие способы манипулирования монадическими значениями) более подробно.

...