2012-08-07 68 views
21

在併發庫GHC.Conc中有一個叫做numCapabilities的函數。它的類型爲numCapabilities :: Int,它實際上會返回您通過命令行標誌傳遞的某個數字(例如,如果選項爲+RTS -N 5,則爲5)。爲什麼numCapabilities是純函數?

但是,getArgs(類型:IO [String])在本質上是相同的(它返回未解析的非運行時參數),但不是純函數。

如果唯一的藉口是純代碼中經常需要numCapabilities,純代碼中不需要其他命令行選項而不是

我是否有東西丟失或者是numCapabilities設計缺陷還是我可以寫下面的怪物?

myGetArgs = unsafePerformIO getArgs 
+6

我現在想恰恰相反:由於getArgs'的'值你的程序的運行過程中不會改變,我不知道是什麼原因,它需要/應該是'IO'。 – sepp2k 2012-08-07 17:31:59

+4

正如其中一個答案所述,它取決於如何定義_pure_表達式。我將表達式定義爲_pure_,如果它不依賴於任何東西,除了表達式本身。按照這個定義'numCapabilities'不是純粹的,所以有一個'Int'類型應該被認爲是一個設計缺陷。您可能會對Conal Elliott的博客文章[Haskell純度概念]感興趣(http://conal.net/blog/posts/notions-of-purity-in-haskell)。 – 2012-08-07 18:05:12

+0

'numCapabilities'不需要返回賦給'-N'的值 - 它只是調用'getNumCapabilities',因此返回當時的許多功能。我認爲這是一個錯誤,但是很難說在GHC模塊中可以依靠什麼保證。 – 2012-08-18 21:56:20

回答

21

我已經看到在這種情況下做什麼非常不同的意見。有些人認爲編譯之間可能有所不同的值不應該是純粹的,有些人認爲只要在程序的本地運行時(即在「設置」某個「配置」後)某個值不會改變main),它應該是純粹的。

base套餐似乎已經在中間地帶落戶了。 numCapabilities將不會(據我所知)在運行時更改,但getArgs可能

這是因爲有一個withArgs函數可以更改通過getArgs獲得的參數。所以,這就是答案。

+1

['setNumCapabilities'](http:// www .haskell.org/GHC /文檔/最新/ HTML /庫/基/ GHC-Conc.html#五:setNumCapabilities)? – 2012-08-07 18:03:53

+9

'numCapabilities'將參數返回給'-N#',而'getNumCapabilities'返回實際有多少功能。 'setNumCapabilities'改變了'getNumCapabilities'獲取的實際數量。 'get *'和'set *'函數都在'IO'單元中。 – dflemstr 2012-08-07 18:05:29

+0

這導致了爲什麼既有'numCapabilities''''getNumCapabilities',也不是'args'和'getArgs'這兩個問題 – helami 2012-08-07 18:06:52

3

我想說這是一個錯誤,但這取決於人們認爲純度是什麼。請參閱文章Notions of purity in Haskell及其討論。簡而言之,帖子的論點是類型有意義,Int對於像numCapabilities這樣的執行上下文相關的東西沒有空間。

15

親愛的。如果你看看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臭名昭著的後門被錯誤地標註。

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