21

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

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

如果唯一的借口是numCapabilities纯代码中经常需要它,那么纯代码中不需要其他命令行选项的方式是什么

我是否缺少某些东西,或者是numCapabilities设计缺陷还是允许我编写以下怪物?

myGetArgs = unsafePerformIO getArgs
4

4 回答 4

22

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

base包裹似乎已处于中间立场。numCapabilities 不会(据我所知)在运行时更改,但getArgs 可能.

这是因为有一个withArgs函数可以更改您通过getArgs. 所以,这就回答了。

于 2012-08-07T17:34:21.383 回答
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.

于 2012-08-17T09:18:16.570 回答
3

我会说这是一个错误,但这取决于一个人认为纯度是什么。请参阅Haskell 中的纯度概念及其讨论。简单地说,帖子的论点是类型是有意义的,并且Int对于类似的东西的含义没有空间numCapabilities,这是依赖于执行上下文的。

于 2012-08-17T04:23:38.533 回答
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   !!!
于 2013-04-28T11:24:56.687 回答