Генератор псевдослучайных чисел, конечно, может использоваться за пределами IO
, просто сохраняя текущее значение генератора вместе с вероятностной структурой чистых данных и обновляя ее при построении модифицированных версий. Недостатком этого является то, что PRNG будет более явно детерминированным, чем в нечистой программе, так как ничто за пределами единой структуры данных не сможет его обновить. Если только статистические свойства имеют значение, это не представляет проблемы, но может быть причиной для беспокойства в противном случае.
С другой стороны, сокрытие нечистого PRNG, возможно, является оправданным использованием unsafePerformIO
, как в Ganesh Sittampalam . Это явно нарушает ссылочную прозрачность, но только в той степени, в которой PRNG будет возвращать непредсказуемые, противоречивые значения - вот и весь смысл! Однако необходимо соблюдать осторожность, поскольку компилятор может сделать неверные предположения о коде, потому что он выглядит чисто.
Но на самом деле ни один из этих подходов не является чрезвычайно привлекательным. Использование unsafePerformIO
неудовлетворительно и потенциально опасно. Потоки в состоянии PRNG просты, но накладывают (потенциально ложную) строгую последовательность на любые вычисления, которые его используют. Программисты Haskell не отказываются ни от безопасности, ни от лени (и это правильно!), И, конечно, структуры данных, ограниченные IO
, имеют ограниченную полезность. Поэтому, чтобы ответить на часть вашего вопроса, программисты на Haskell, скорее всего, избегают таких структур.
Что касается того, «как Хаскелл может справиться» с такими вещами, я бы предположил, что это неправильный вопрос, чтобы задать .
Что действительно сводится к тому, что многие структуры данных и алгоритмы неявно предполагают (и оптимизируют для) императивный, нечистый, строгий язык , и хотя он, безусловно, возможно реализовать их в Haskell, редко желательно , потому что (даже игнорируя внутреннюю реализацию) их использование налагает на ваш код структуру и подход, который очень не идиоматичен. Кроме того, поскольку Haskell нарушает эти неявные допущения, производительность часто снижается (иногда очень сильно).
Необходимо понять, что алгоритмы и структуры данных являются средством, а не целью . Редко бывает так, что требуется одна конкретная реализация - то, что требуется , , обычно соответствует характеристикам производительности . Поиск структур данных / алгоритмов, которые предлагают желаемые характеристики и в то же время идиоматичны, Haskell почти всегда является лучшим планом и, скорее всего, будет лучше, чем попытка втиснуть строгий императивный колышек в ленивое функциональное отверстие.
Эта ошибка, пожалуй, чаще всего встречается в подмножестве программистов, которые никогда не сталкивались с проблемой, которую не могли решить с помощью хеш-таблицы, но для многих из нас привычка проста. Правильный подход состоит в том, чтобы перестать думать «как реализовать это решение в Haskell», а вместо этого «каков наилучший способ решения моей проблемы в Haskell» . Вы можете быть удивлены, как часто ответы отличаются; Я знаю, что я часто!