выбор случайного элемента из списка - PullRequest
0 голосов
/ 19 октября 2018

Итак, в моем проекте у меня есть постоянная функция, которая возвращает массив:

import System.Random

giveList :: [Int]
giveList = [8,9,4,5,2]

, и я бы хотел случайным образом выбрать элемент из этого списка, например:

seed::Int
seed = 40

generator = mkStdGen seed

giveRandomElement :: Int
giveRandomElement = giveList !! rand where
    n = length tetrominoes
    (rand,generator) = randomR (0,(n-1)) generator

Однако, это не компилируется из-за генератора, я хотел бы сохранить генератор как глобальную переменную, чтобы мне не приходилось продолжать давать его функциям.Я также не хочу иметь дело с оболочками ввода-вывода, так как я могу это сделать?

Спасибо за помощь: -)

Ответы [ 2 ]

0 голосов
/ 20 октября 2018

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

Извините, функция giveRandomElement :: Int, которая возвращает другое случайное число каждый раз, когда вы вызываете его не ссылочно-прозрачный , поэтому чистота Хаскелла не позволяет вам делать то, что вы хотите.

Я думаю, что работа со случайными значениямиотличная возможность узнать о монады. MonadRandom имеет очень гибкий интерфейс для написания функций, результаты которых являются случайными:

die :: (MonadRandom m) => m Int
die = getRandomR (1, 6)

rollDice :: (MonadRandom m) => m (Int, Int)
rollDice = do
    x <- die
    y <- die
    return (x, y)

-- Your example
giveRandomElement :: (MonadRandom m) => m Int
giveRandomElement = do
    let n = length tetrominoes
    i <- getRandomR (0, n-1)
    return (giveList !! i)

Реализации этой монады пропустят состояние случайности через ваши случайные функции для вас.Есть даже instance MonadRandom IO, который позволяет писать

main :: IO ()
main = do
    x <- giveRandomElement
    print x
0 голосов
/ 19 октября 2018

Пример рабочего кода

import System.Random

seed::Int
seed = 40

giveList :: [Int]
giveList = [8,9,4,5,2]

generator = mkStdGen seed

giveRandomElement :: Int
giveRandomElement = giveList !! rand where
  n = length giveList
  (rand, _) = randomR (0,(n-1)) generator

Но это, вероятно, не сработает, как вы хотите.

giveRandomElement всегда даст один и тот же результат.Это чистая функция без каких-либо входов, так что она должна делать?Он может быть только постоянным.

Вам нужно либо использовать IO, либо вам нужно пропустить ваш генератор через ваш код и где-то его отслеживать.

Полученная вами ошибка компилятора:

test.hs:14:23: error:
    • Ambiguous type variable ‘g0’ arising from a use of ‘randomR’
      prevents the constraint ‘(RandomGen g0)’ from being solved.
      Relevant bindings include generator :: g0 (bound at test.hs:14:10)
      Probable fix: use a type annotation to specify what ‘g0’ should be.
      These potential instance exist:
        instance RandomGen StdGen -- Defined in ‘System.Random’
    • In the expression: randomR (0, (n - 1)) generator
      In a pattern binding:
        (rand, generator) = randomR (0, (n - 1)) generator
      In an equation for ‘giveRandomElement’:
          giveRandomElement
            = giveList !! rand
            where
                n = length giveList
                (rand, generator) = randomR (0, (n - 1)) generator
   |
14 |   (rand, generator) = randomR (0,(n-1)) generator
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^

потому что вы определили символ generator в giveRandomElement в терминах самого себя, и поэтому компилятор не смог определить его тип.(Объявление верхнего уровня generator в этом случае не использовалось, поскольку (rand, generator) = уже затенял символ после знака равенства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...