plataforma para online mac descargar compiler haskell ghc

haskell - para - Definir la aplicación estricta($!) Yo mismo no resulta en el mismo rendimiento



haskell platform (1)

Estoy leyendo esta entrada de blog de Michael Snoyman recientemente. En un ejercicio sugerido allí, traté de definir $! operador por mi cuenta:

import Prelude hiding ( ($!) ) ($!) :: (a -> b) -> a -> b ($!) f x = x `seq` f x mysum :: [Int] -> Int mysum list0 = go list0 0 where go [] total = total go (x:xs) total = go xs $! total + x main = print $ mysum [1..1000000]

Pensé que esto funciona bien, aunque el uso de la memoria era terrible. Mi primera pregunta es la siguiente. ¿Por qué no funcionó bien?

Entonces, comprobé su definición en Preludio. Se lee:

($!) :: (a -> b) -> a -> b f $! x = let !vx = x in f vx -- see #2273

Entonces, lo copié en mi código:

{-# LANGUAGE BangPatterns #-} import Prelude hiding ( ($!) ) ($!) :: (a -> b) -> a -> b ($!) f x = let !vx = x in f vx mysum :: [Int] -> Int mysum list0 = go list0 0 where go [] total = total go (x:xs) total = go xs $! total + x main = print $ mysum [1..1000000]

y el resultado fue:

Linking mysum4 ... 500000500000 209,344,064 bytes allocated in the heap 130,602,696 bytes copied during GC 54,339,936 bytes maximum residency (8 sample(s)) 66,624 bytes maximum slop 80 MB total memory in use (0 MB lost due to fragmentation)

¡Puedes ver cuán terrible es esto comparado con el resultado de usar $! de Prelude $! operador:

Linking mysum4 ... 500000500000 152,051,776 bytes allocated in the heap 41,752 bytes copied during GC 44,384 bytes maximum residency (2 sample(s)) 21,152 bytes maximum slop 1 MB total memory in use (0 MB lost due to fragmentation)

Mi segunda pregunta es ¿de dónde viene esta diferencia?

Además, creo que puede reescribirse así:

($!) :: (a -> b) -> a -> b f $! !x = f x

¿Hay alguna razón para no hacer esto? Esta es mi tercera pregunta.


Jajaja Es un tema de precedencia. Se te olvidó pegar la línea:

infixr 0 $!

y así, cuando usas tu propia versión, se analiza como

go (x:xs) total = (go xs $! total) + x

que obviamente tiene un rendimiento terrible. Es casi una coincidencia que incluso te da la respuesta correcta.