Подтвердить что ты не робот

Почему numCapabilities является чистой функцией?

В библиотеке concurrency GHC.Conc есть функция numCapabilities. Его тип numCapabilities :: Int, и он фактически возвращает некоторое число, которое вы передали с помощью флага командной строки (например, 5, если параметры +RTS -N 5).

Однако getArgs (тип: IO [String]) делает практически то же самое (он возвращает непараметрированные аргументы без запуска), но не является чистой функцией.

Если единственным оправданием является то, что numCapabilities часто требуется в чистом коде, каким образом не нужны другие параметры командной строки в чистом коде?

Мне что-то не хватает или это numCapabilities недостаток дизайна, или мне разрешено писать следующего монстра?

myGetArgs = unsafePerformIO getArgs
4b9b3361

Ответ 1

Я видел очень разные мнения о том, что делать в таких ситуациях. Некоторые считают, что значения, которые могут различаться между компиляторами, не должны быть чистыми, а некоторые считают, что до тех пор, пока значение не изменится во время вашей локальной локализации (то есть после некоторой "конфигурации" "setup" в main), он должен быть чистым.

Пакет base, похоже, поселился на средней земле. numCapabilities не будет (насколько мне известно) изменяться во время выполнения, но getArgs может.

Это потому, что есть функция withArgs, которая изменяет аргументы, которые вы получаете через getArgs. Итак, это отвечает на это.

Ответ 2

Боже мой. Если вы посмотрите на определение numCapabilities, вы увидите, что это просто:

numCapabilities :: Int
numCapabilities = unsafePerformIO $ getNumCapabilities

а следующие сеансы ghci иллюстрируют проблему:

[[email protected] ~]$ ghci
GHCi, version 7.4.2: http://www.haskell.org/ghc/  :? for help
Loading [...]
ghci> :m +GHC.Conc
ghci> numCapabilities
1
ghci> setNumCapabilities 2
ghci> numCapabilities
1
ghci> :q
Leaving GHCi.

[[email protected] ~]$ ghci
GHCi, version 7.4.2: http://www.haskell.org/ghc/  :? for help
Loading [...]
ghci> :m +GHC.Conc
ghci> setNumCapabilities 2
ghci> numCapabilities
2

Это определенно плохо - значение numCapabilities зависит от того, когда оно оценивается в отношении любых вызовов setNumCapabilities, которые могут существовать в вашей программе. Обратите внимание, что в первом сеансе numCapabilities оставался согласованным, поскольку IO выполняется только при первом его вычислении. Однако при наличии вставки (имя не отмечено NOINLINE или что-то еще) даже это может быть неверно - вы могли бы в принципе получить два разных значения из двух вхождений numCapabilities (хотя на практике я не смог чтобы это произошло).

Итак, ответ заключается в том, что numCapabilities не является чистой функцией, но ошибочно помечен как таковой пресловутой задней дверью unsafePerformIO.

Ответ 3

Я бы сказал, что это ошибка, но это зависит от того, что думает о чистоте. См. Сообщение Понятия о чистоте в Haskell и его обсуждение. Проще говоря, аргумент post состоит в том, что типы имеют смысл, и нет места в значении Int для чего-то вроде numCapabilities, который зависит от исполнения.

Ответ 4

numCapabilities дает начальное значение getNumCapabilities, так или иначе присутствует аргумент флага RTS -N, поэтому тип должен быть тем же.

Вы пробовали это с более высоким номером, чем ваш компьютер макс. одновременные потоки?

$ ghci +RTS -N99
GHCi, version 7.4.2: http://www.haskell.org/ghc/  :? for help
Prelude> :m +GHC.Conc
Prelude GHC.Conc> numCapabilities
99
Prelude GHC.Conc> getNumCapabilities
99   !!!