Как написать функцию haskell без ввода-вывода в типе sig, скрывая изменения 'state' - PullRequest
7 голосов
/ 20 мая 2011

Я написал функцию в haskell, которая принимает несколько параметров, таких как Word32, String (игнорировать каррирование) и выводит IO Word32. Теперь это функция в истинном смысле: для тех же самых входов, выход всегда будет одинаковым . Там нет никаких побочных эффектов. Причина, по которой функция возвращает IO Word32 вместо Word32, заключается в том, что функция обновляет несколько 32-битных регистров линейного сдвига с обратной связью (lfsr) и другие регистры несколько раз в цикле, чтобы вычислить окончательный вывод Word32.

У меня такой вопрос: учитывая, что эта функция фактически не имеет побочных эффектов , возможно ли скрыть эти обновления регистров внутри реализации функции, чтобы функция возвращала Word32, а не IO Word32? Если да, то как?

Ответы [ 3 ]

13 голосов
/ 20 мая 2011

Да!Haskell может сделать это.

Монада ST

Если вы на самом деле используете изменяемые состояния (регистры), которые полностью скрыты от наблюдателя за пределами функции, то выв монаде ST , только для эффектов памяти.Вы входите в мир ST через runST, и при выходе из функции все эффекты гарантированно не будут видны.

Это точно подходящая вычислительная среда для работы с локальным изменяемым состоянием.

Чисто функциональное состояние: монада состояний

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

IO и unsafePerformIO

Наконец, если у вас есть локальные, изменяемые эффекты, как вмонаду ST, но по тем или иным причинам вам понадобятся операции ввода-вывода в этом состоянии (например, через вызов FFI), вы можете симулировать монаду ST с почти такой же безопасностью, используя unsafePerformIO вместо runST, чтобы ввести локальную среду ввода-вывода.Поскольку у монады ввода-вывода нет хороших типов для обеспечения абстракции, вам необходимо вручную убедиться, что побочные эффекты не будут заметны.

5 голосов
/ 20 мая 2011

Если вы импортировали эту функцию с использованием FFI, просто удалите IO из возвращаемого типа. В противном случае используйте unsafePerformIO :: IO a -> a из System.IO.Unsafe. Обратите внимание, что эта функция является одной из самых опасных функций в Haskell. Не используйте его, если вы не уверены в последствиях. Но для твоих целей все в порядке.

3 голосов
/ 20 мая 2011

Да, это было бы законным использованием unsafePerformIO. Но это нормально, если вы действительно уверены, что видимых эффектов нет.

...