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