2012-08-07 10 views
21

同時実行ライブラリGHC.Concには、numCapabilitiesという関数があります。そのタイプはnumCapabilities :: Intであり、実際にはコマンドラインのフラグによって渡された数値が返されます(例:+RTS -N 5の場合は5)。なぜnumCapabilitiesは純粋な関数ですか?

ただし、getArgs(タイプ:IO [String])は基本的に同じです(解析されていない非実行時引数を返します)が、純関数ではありません。

純粋なコードではnumCapabilitiesがしばしば必要な場合は、他のコマンドラインオプションはありませんは純粋なコードで必要ですか?

アムI何か欠落しているかのどちらかnumCapabilities設計上の欠陥があるか、私には、以下のモンスターを書くさせて頂いておりますか!

myGetArgs = unsafePerformIO getArgs 
+6

私は現在、プログラムの実行中に 'getArgs'の値が決して変更されないので、' IO'にする必要がある/なぜそうであるべきか正確にはわかりません。 – sepp2k

+4

答えの1つで述べたように、どのように_pure_式を定義するかによって異なります。私はそれが表現そのもの以外のものに依存していない場合、式を_pure_と定義します。この定義によって、 'numCapabilities'は純粋ではないので、' Int'の型は設計上の欠陥とみなされるべきです。 Conal Elliottのブログ記事「Haskellにおける純度の概念」(http://conal.net/blog/posts/notions-of-purity-in-haskell)に興味があるかもしれません。 –

+0

'numCapabilities'は' -N'に与えられた値を返す必要はありません。単に 'getNumCapabilities'を呼び出します。私はこれをバグと考えていますが、あなたがGHCモジュールに頼ることができる保証については言い難いです。 –

答えて

21

私はこのような状況で何をすべきかについて非常に様々な見方を見てきました。一部の人は、の間で変化する可能性のある値はが純粋であるべきではなく、プログラムのローカルランタイム中に値が変更されない限り(つまり、いくつかの「設定」が「設定」された後) main)、純粋でなければなりません。

baseパッケージには、中間地に定住しているようです。 numCapabilitiesしません(私の知る限り)実行時に変更はなく、getArgsかもしれない。あなたがgetArgs経由で取得する引数を変更withArgs機能があるので

です。だから、それはそれに答える。

+1

['setNumCapabilities'] .haskell.org/ghc/docs/latest/html/libraries/base/GHC-Conc.html#v:setNumCapabilities)? –

+9

'numCapabilities'はパラメータを' -N# 'に返し、' getNumCapabilities'は実際にそこにある能力を返します。 'setNumCapabilities'は' getNumCapabilities'によって取り出される実際の数を変更します。 'get *'と 'set *'関数はどちらも 'IO'モナドにあります。 – dflemstr

+0

これは 'numCapabilities'と' getNumCapabilities'の両方があり、 'args'と' getArgs'の両方ではないという理由につながります。 – helami

3

私はそれが間違いだと言うだろうが、それは1つが純度があると考えるかに依存します。投稿Notions of purity in Haskellとその議論を参照してください。簡単に言えば、投稿の引数は型に意味があり、Intの意味にはnumCapabilitiesのようなものがあります。これは実行コンテキストに依存します。

15

ああ親愛

numCapabilities :: Int 
numCapabilities = unsafePerformIO $ getNumCapabilities 

と、次のGHCiのセッションは、問題を示します: - numCapabilitiesの値

[[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の定義を見れば、あなたはそれだけで見ることができますプログラムに存在する可能性のある呼び出しについて評価される時点によって異なります。最初のセッションでは、IOが最初に評価されたときにのみ実行されるため、numCapabilitiesは一貫していました。しかし、実際にはないかもしれないにもかかわらず、インライン展開(名前にNOINLINEなどの印がついていません)がある場合、原則としてnumCapabilitiesの2回の出現から2つの異なる値を得ることができます(実際には、これが起こる)。

だから、答えは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 !!! 
関連する問題