为什么numCapabilities是纯函数?

hel*_*ami 21 haskell standard-library

在并发库GHC.Conc中有一个名为的函数numCapabilities.它的类型是numCapabilities :: Int,它实际上返回一些你通过命令行标志传递的数字(例如,5如果选项是+RTS -N 5).

但是,getArgs(type IO [String]:)基本上相同(它返回未解析的非运行时参数)但不是纯函数.

如果唯一借口是numCapabilities往往需要在纯代码,以什么方式不其他命令行选项不能在纯代码需要?

我缺少什么或者是numCapabilities设计缺陷还是我允许写下面的怪物?

myGetArgs = unsafePerformIO getArgs
Run Code Online (Sandbox Code Playgroud)

dfl*_*str 21

在这样的情况下,我看到了很多不同的观点.有些人认为编译之间可能不同的值不应该是纯粹的,有些人认为只要在程序的本地运行时(即在某些"配置"已经"设置"之后main)值没有改变,它应该是纯粹的.

base包装似乎对中等地解决.numCapabilities 不会(据我所知)在运行期间改变,但getArgs 可能.

这是因为有一个withArgs函数可以改变你通过的args getArgs.所以,答案就是这样.

  • 因为在`numCapabilities`之后添加了`setNumCapabilities`,并且不推荐使用`numCapabilities`(如图所示,库作者说你应该在文档中使用`num*功能`中的`get*`函数). (12认同)
  • `numCapabilities`将参数返回到'-N#`,而`getNumCapabilities`返回实际有多少功能.`setNumCapabilities`改变实际数字,由`getNumCapabilities`检索.`get*`和`set*`函数都在`IO` monad中. (9认同)
  • 这是一个弃用的价值.它肯定用于返回之前传递给`-N#`的参数,因为无法更改该数字(因为没有`setNumCapabilities`).在引入新函数之后,不推荐使用`numCapabilities`,并且仅保留兼容性,因此对于不知道`set*`的程序,它仍然表现一致.你不应该将它用于新程序; 换句话说,包含`numCapabilities`和`setNumCapabilities`的程序在语义上是不正确的. (2认同)

Ben*_*ood 15

哦,亲爱的.如果你看一下定义numCapabilities,你可以看到它只是:

numCapabilities :: Int
numCapabilities = unsafePerformIO $ getNumCapabilities
Run Code Online (Sandbox Code Playgroud)

以下ghci会话说明了问题:

[ben@euler ~]$ 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.

[ben@euler ~]$ ghci
GHCi, version 7.4.2: http://www.haskell.org/ghc/  :? for help
Loading [...]
ghci> :m +GHC.Conc
ghci> setNumCapabilities 2
ghci> numCapabilities
2
Run Code Online (Sandbox Code Playgroud)

绝对是错误的 - 值numCapabilities取决于何时根据setNumCapabilities程序中可能存在的任何调用进行评估.请注意,在第一个会话中,numCapabilities保持一致,因为IO它仅在第一次评估时执行.然而,在内联的情况下(名称没有标记为NOINLINE或任何东西),即使这可能不是真的 - 你原则上可以从两次出现时获得两个不同的值numCapabilities(尽管在实践中我无法做到这一点)发生).

所以答案是,这numCapabilities 不是一个纯粹的功能,而是由臭名昭着的后门错误地标记出来的unsafePerformIO.