2012-08-07 12 views
21

En la biblioteca de concurrencia GHC.Conc hay una función llamada numCapabilities. Su tipo es numCapabilities :: Int y en realidad devuelve un número que pasó por el indicador de línea de comando (por ejemplo, 5 si las opciones son +RTS -N 5).¿Por qué numCapabilities es una función pura?

Sin embargo, getArgs (tipo: IO [String]) hace esencialmente lo mismo (devuelve los argumentos no en tiempo de ejecución no analizados) pero no es una función pura.

Si la única excusa es que a menudo se necesita numCapabilities en código puro, ¿de qué manera no son necesarias otras opciones de línea de comando en código puro?

¿Me falta algo o es numCapabilities un error de diseño o puedo escribir el siguiente monstruo?

myGetArgs = unsafePerformIO getArgs 
+6

ahora estoy preguntando lo contrario: Como el valor de 'getArgs' nunca cambia durante la ejecución de su programa, no estoy muy seguro de por qué se necesita/debe estar en' IO'. – sepp2k

+4

Como se menciona en una de las respuestas, depende de cómo se define una expresión _pure_. Definiría una expresión como _pure_ iff no depende de nada más que la expresión misma. Según esta definición, 'numCapabilities' no es puro, por lo que tener un tipo de' Int' debe considerarse como un defecto de diseño. Puede que le interese la publicación de blog de Conal Elliott [Nociones de pureza en Haskell] (http://conal.net/blog/posts/notions-of-purity-in-haskell). –

+0

'numCapabilities' no necesita devolver el valor dado a' -N' - simplemente llama a 'getNumCapabilities', por lo que devuelve todas las capacidades que haya en el momento. Creo que esto es un error, pero es difícil decir qué garantías puedes confiar en los módulos de GHC. –

Respuesta

21

He visto muy diversas opiniones sobre qué hacer en situaciones como esta. Algunos piensan que los valores que pueden variar entre compilan no deben ser puros, y algunos piensan que mientras un valor no cambie durante el tiempo de ejecución local de su programa (es decir, después de que se haya "configurado" una "configuración") main), debe ser puro.

El paquete base parece haberse asentado en un punto medio. numCapabilitiescambiar no (por lo que yo sé) durante el tiempo de ejecución, pero getArgs fuerza.

Esto es porque hay una función withArgs que cambia los argumentos que obtienes a través de getArgs. Entonces, eso responde eso.

+1

¿Qué pasa con ['setNumCapabilities'] (http: // www .haskell.org/ghc/docs/latest/html/libraries/base/GHC-Conc.html # v: setNumCapabilities)? –

+9

'numCapabilities' devuelve el parámetro a' -N # ', mientras que' getNumCapabilities' devuelve la cantidad de capacidades que realmente existen. 'setNumCapabilities' cambia el número real, que es recuperado por' getNumCapabilities'. Ambas funciones 'get *' y 'set *' están en la mónada 'IO'. – dflemstr

+0

Lo que lleva a la pregunta de por qué hay tanto 'numCapabilities' y' getNumCapabilities' y no tanto 'args' como' getArgs' – helami

3

Yo diría que es un error, pero depende de lo que uno piense que es la pureza. Ver la publicación Notions of purity in Haskell y su discusión. En pocas palabras, el argumento de la publicación es que los tipos tienen significado, y no hay espacio en el significado de Int para algo como numCapabilities, que depende de la ejecución del contexto.

15

Oh estimado. Si nos fijamos en la definición de numCapabilities, se puede ver que es justo:

numCapabilities :: Int 
numCapabilities = unsafePerformIO $ getNumCapabilities 

y las siguientes sesiones ghci ilustrar el problema:

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

Ésta es definitivamente mal - el valor de numCapabilities depende de cuándo se evalúa con respecto a cualquier llamada setNumCapabilities que pueda existir en su programa. Tenga en cuenta que en la primera sesión, numCapabilities se mantuvo constante, ya que el IO solo se ejecuta la primera vez que se evalúa. Sin embargo, en presencia de Inline (el nombre no está marcado NOINLINE ni nada), incluso eso puede no ser cierto. En principio, podría obtener dos valores diferentes de dos ocurrencias de numCapabilities (aunque en la práctica no he podido hacer esto pasa).

Así que la respuesta es que no es numCapabilities una función pura, pero está marcado erróneamente como tal por la puerta de atrás notorio de unsafePerformIO.

0

numCapabilities da el valor inicial de getNumCapabilities, ya sea que el argumento de bandera RTS -N esté presente o no, por lo que el tipo debe ser el mismo.

¿Lo ha probado con un número mayor que su computadora como máximo? hilos simultáneos?

$ 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 !!! 
Cuestiones relacionadas