2012-01-03 7 views
6

En el siguiente código generalizada:modo por defecto de ejecución de código en Haskell

nat = [1..xmax] 
xmax = *insert arbitrary Integral value here* 

setA = [2*x | x <- nat] 
setB = [3*x | x <- nat] 

setC = [4*x | x <- nat] 
setD = [5*x | x <- nat] 

setOne = setA `f` setB 
setTwo = setC `f` setD 

setAll = setOne ++ setTwo 

setAllSorted = quicksort setAll 

(tenga en cuenta que 'f' es sinónimo de una función del tipo

f :: Integral a => [a] -> [a] -> [a] 

que no es simplemente ++)

¿Cómo se maneja Haskell al intentar imprimir setAllSorted?

¿obtiene los valores de setA y setB, calcula setOne y luego solo conserva los valores de setOne en la memoria (antes de calcular todo lo demás)?

¿O Haskell guarda todo en la memoria hasta que obtiene el valor para setAllSorted?

Si este último es el caso, ¿cómo podría especificar (utilizando main, do funciones y todas esas otras cosas IO) que haga el anterior en su lugar?

¿Puedo decirle al programa en qué orden calcular y recoger basura? Si es así, ¿cómo lo haría?

+1

Haskell no define en absoluto cómo se ejecuta su código, solo cuál debe ser el resultado; esta pregunta es intrínsecamente específica de la implementación. – ehird

Respuesta

9

La cabeza de setAllSorted es necesariamente menos que igual a todos los elementos de la cola. Por lo tanto, para determinar la altura, se deben calcular todos los setOne y setTwo. Además, dado que todos los conjuntos son formularios aplicativos constantes, creo que no serán recolectados después de ser calculados. Es probable que los números mismos se compartan entre los conjuntos, pero los nodos contras que los unen probablemente no lo sean (su suerte con algunos dependerá de la definición de f).

+2

Aunque son CAF, se pueden recopilar si el compilador puede determinar que ya no se hace referencia a ellos después de la impresión. Si el programa es 'main = print setAllSorted', hay muchas posibilidades de que GHC (con optimizaciones) recolecte la basura que ya no necesita. Sin embargo, esa es solo una reducción de factor constante de la memoria pico. –

+0

¿significa "factor constante" que dará una mayor reducción para cantidades mayores de datos? Es decir, ¿significa que la reducción máxima de memoria es directamente proporcional a la cantidad de datos calculados y, por lo tanto, a la recolección de basura? –

7

Debido a la pereza, Haskell evalúa las cosas a pedido. Puede pensar en la impresión que se hace al final como elementos "tirando" de la lista setAllSorted, y que podría arrastrar consigo otras cosas.

Es decir, la ejecución de este código es algo como esto:

  1. Impresión primero evalúa el primer elemento de setAllSorted.
  2. Dado que esto proviene de un procedimiento de clasificación, será necesario evaluar todos los elementos de setAll. (Dado que el elemento más pequeño podría ser el último).
  3. La evaluación del primer elemento de setAll requiere la evaluación del primer elemento de setOne.
  4. La evaluación del primer elemento de setOne depende de cómo se implemente f. Puede requerir todo o nada de setA y setB para ser evaluado.
  5. Después de que hayamos terminado de imprimir el primer elemento de setAllSorted, setAll habrá sido evaluado por completo. No hay más referencias a setOne, setTwo y los conjuntos más pequeños, por lo que todos estos son ahora elegibles para la recolección de basura. El primer elemento de setAllSorted también se puede reclamar.

tanto, en teoría, este código se mantendrá en la memoria setAll mayor parte del tiempo, mientras que setAllSorted, setOne y setTwo es probable que sólo ocupan una cantidad constante de espacio en cualquier momento.Dependiendo de la implementación de f, lo mismo puede ser cierto para los conjuntos más pequeños.

Cuestiones relacionadas