2012-08-07 10 views
21

In der Concurrency-Bibliothek GHC.Conc gibt es eine Funktion namens numCapabilities. Sein Typ ist und es gibt tatsächlich eine Zahl zurück, die Sie vom Befehlszeilen-Flag übergeben haben (z. B. 5, wenn die Optionen +RTS -N 5 sind).Warum ist numCapabilities eine reine Funktion?

Jedoch getArgs (Typ: IO [String]) tut im Wesentlichen das gleiche (es gibt die ungeparsten Nicht-Laufzeitargumente zurück), ist aber keine reine Funktion.

Wenn die einzige Entschuldigung ist, dass numCapabilities oft in reinem Code benötigt wird, in welcher Weise sind nicht andere Befehlszeilenoptionen nicht in reinem Code benötigt?

Bin mir etwas fehlt oder ist entweder numCapabilities ein Designfehler oder darf ich folgendes Monster schreiben?

myGetArgs = unsafePerformIO getArgs 
+6

Ich frage mich jetzt das Gegenteil: Da der Wert von 'getArgs' nie während des Laufs des Programms ändert, ich bin mir nicht ganz sicher, warum es muss/sollte in' IO' sein. – sepp2k

+4

Wie in einer der Antworten erwähnt, hängt es davon ab, wie man einen _pure_ Ausdruck definiert. Ich würde einen Ausdruck als _pure_ definieren, wenn er nicht von etwas anderem als dem Ausdruck selbst abhängt. Durch diese Definition ist 'numCapabilities' nicht rein, daher sollte ein Typ von' Int' als Designfehler betrachtet werden. Vielleicht interessieren Sie sich für Conal Elliotts Blogpost [Reinheitsvorstellungen in Haskell] (http://conal.net/blog/posts/notions-of-purity-in-haskell). –

+0

'numCapabilities' muss den angegebenen Wert nicht an '-N' zurückgeben - es ruft nur 'getNumCapabilities' auf, gibt also viele Funktionen zurück, die es zu der Zeit gibt. Ich denke, das ist wirklich ein Fehler, aber es ist schwer zu sagen, auf welche Garantien man sich in den GHC-Modulen verlassen kann. –

Antwort

21

Ich habe sehr unterschiedliche Ansichten darüber gesehen, was in solchen Situationen zu tun ist. Einige denken, dass Werte, die zwischen Kompilieren variieren können, nicht rein sein sollten, und einige denken, dass solange sich ein Wert während der lokalen Laufzeit Ihres Programms nicht ändert (dh nachdem einige "Konfiguration" in "eingerichtet" worden ist) main), sollte es rein sein.

Das base Paket scheint sich in einem mittleren Bereich angesiedelt zu haben. numCapabilitieswird nicht (so weit ich weiß) während der Laufzeit ändern, aber getArgskönnte.

Dies liegt daran, dass es eine withArgs Funktion gibt, die die Argumente ändert, die Sie über getArgs erhalten. Also, das beantwortet das.

+1

Was ist mit ['setNumCapabilities'] (http: // www .haskell.org/ghc/docs/neueste/html/libraries/base/GHC-Conc.html # v: setNumCapabilities)? –

+9

'numCapabilities' gibt den Parameter an' -N # 'zurück, während' getNumCapabilities' die Anzahl der tatsächlich vorhandenen Funktionen zurückgibt. 'setNumCapabilities' ändert die tatsächliche Anzahl, die von' getNumCapabilities' abgerufen wird. Die Funktionen 'get *' und 'set *' befinden sich in der IO-Monade. – dflemstr

+0

Dies führt zu der Frage, warum es 'numCapabilities' und' getNumCapabilities' gibt und nicht sowohl 'args' als auch' getArgs'. – helami

3

Ich würde sagen, es ist ein Fehler, aber es hängt davon ab, was man für Reinheit hält. Siehe den Beitrag Notions of purity in Haskell und seine Diskussion. Einfach gesagt, das Argument des Posts ist, dass Typen eine Bedeutung haben, und es gibt keinen Platz in der Bedeutung von Int für etwas wie numCapabilities, das Ausführungskontext-abhängig ist.

15

Oh lieb. Wenn Sie bei der Definition von numCapabilities anschaut, kann man sehen, es ist nur:

numCapabilities :: Int 
numCapabilities = unsafePerformIO $ getNumCapabilities 

und die folgenden GHCI Sitzungen veranschaulichen das Problem:

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

Dies ist definitiv schlecht - der Wert numCapabilities hängt davon ab, wenn es in Bezug auf alle setNumCapabilities Aufrufe ausgewertet wird, die in Ihrem Programm vorhanden sein können. Beachten Sie, dass in der ersten Sitzung konsistent blieb, da die IO nur bei der ersten Auswertung ausgeführt wird. In Gegenwart von Inlining (der Name ist nicht als NOINLINE oder irgendwas markiert) ist das sogar nicht wahr - Sie könnten im Prinzip zwei verschiedene Werte von zwei Vorkommen von numCapabilities bekommen (obwohl ich es in der Praxis nicht konnte) Dies geschieht).

Die Antwort ist also, dass numCapabilitiesnicht eine reine Funktion ist, wird aber als solche von der berüchtigten Hintertür von unsafePerformIO fälschlicherweise markiert.

0

numCapabilities gibt den Anfangswert von getNumCapabilities, ob das RTS-N-Flag-Argument vorhanden ist, also sollte der Typ derselbe sein.

Haben Sie es mit einer höheren Anzahl als Ihr Computer versucht max. gleichzeitige Threads?

$ 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 !!! 
Verwandte Themen