在并发库GHC.Conc中有一个名为numCapabilities
的函数。它的类型是numCapabilities :: Int
,它实际上返回了命令行标记传递的一些数字(例如5
,如果选项为+RTS -N 5
)。
但是,getArgs
(类型:IO [String]
)基本上相同(它返回未解析的非运行时参数)但不是纯函数。
唯一的理由是纯代码中经常需要numCapabilities
,纯代码中不需要其他命令行选项 吗?
我缺少什么或是numCapabilities
设计缺陷还是我被允许写下面的怪物?
myGetArgs = unsafePerformIO getArgs
答案 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 !!!