なんてこった。_ の定義を見ると、次のように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 などのマークが付けられていない) が存在する場合でも、それは正しくない可能性があります - 原則として、2 つの出現から 2 つの異なる値を取得できますnumCapabilities
(ただし、実際にはこれを行うことはできませんでした)。起こる)。
答えは、それは純粋な関数でnumCapabilities
はなく、悪名高い のバックドアによって誤ってそのようにマークされているということですunsafePerformIO
。