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 などのマークが付けられていない) が存在する場合でも、それは正しくない可能性があります - 原則として、2 つの出現から 2 つの異なる値を取得できますnumCapabilities(ただし、実際にはこれを行うことはできませんでした)。起こる)。

答えは、それは純粋な関数でnumCapabilities はなく、悪名高い のバックドアによって誤ってそのようにマークされているということですunsafePerformIO

于 2012-08-17T09:18:16.570 に答える
3

それは間違いだと思いますが、純粋さをどう考えるかによります。Haskell での純度の概念とその議論の投稿を参照してください。簡単に言えば、投稿の主張は、型には意味があり、実行コンテキストに依存するのIntようなものには意味の余地がないということです。numCapabilities

于 2012-08-17T04:23:38.533 に答える