为什么numCapabilities是纯函数?

时间:2012-08-07 17:23:26

标签: haskell standard-library

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

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

唯一的理由是纯代码中经常需要numCapabilities,纯代码中不需要其他命令行选项 吗?

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

myGetArgs = unsafePerformIO getArgs

4 个答案:

答案 0 :(得分:21)

我看到在这种情况下该怎么做的观点各不相同。有些人认为在编译之间可能不同的值不应该是纯粹的,并且有些人认为只要在程序的本地运行时期间值没有改变(即在某些“配置”之后)在main)中“设置”,它应该是纯粹的。

base套餐似乎已落户中间地带。 numCapabilities 不会(据我所知)在运行时更改,但getArgs 可能

这是因为有一个withArgs函数会更改您通过getArgs获得的参数。所以,这就解决了这个问题。

答案 1 :(得分:15)

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

numCapabilities :: Int
numCapabilities = unsafePerformIO $ getNumCapabilities

以下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

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

所以答案是numCapabilities 不是一个纯粹的函数,但是unsafePerformIO的臭名昭着的后门错误地标记了它。

答案 2 :(得分:3)

我说这是一个错误,但这取决于人们认为纯度是什么。请参阅帖子Notions of purity in Haskell及其讨论。简单地说,帖子的论点是类型具有意义,并且Int的含义没有numCapabilities的空间,这类似于执行上下文。

答案 3 :(得分:0)

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   !!!