2012-01-20 11 views
11

me leyeron:ViewPatterns y múltiples llamadas en Haskell

http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns

me gusta la idea, quieren utilizar la extensión. Sin embargo, me gustaría asegurarme de una cosa: si la función de vista se evalúa una vez para una sola coincidencia.

Así que vamos a decir que tenemos:

Ahora digamos que invoco f a. ¿Se invoca view dos veces o solo una vez para el argumento dado a?

EDITAR:

me trató de averiguar si este es el caso y escribió lo siguiente:

{-# LANGUAGE ViewPatterns #-} 

import System.IO.Unsafe 

blah (ble -> Nothing) = 123 
blah (ble -> Just x) = x 

ble x = unsafePerformIO $ do 
    putStrLn $ "Inside ble: " ++ show x 
    return x 

main :: IO() 
main = do 
    putStrLn $ "Main: " ++ show (blah $ Just 234) 

salida usando GHC:

Inside ble: Just 234 
Inside ble: Just 234 
Main: 234 

salida usando GHC (con optimización)

Inside ble: Just 234 
Main: 234 

de salida usando GHCi:

Main: Inside ble: Just 234 
Inside ble: Just 234 
234 
+0

GHC tiene un truco especial para evitar el recálculo de expresiones de vista idénticas. – augustss

Respuesta

13

Sólo una vez:

Eficiencia: Cuando se aplica la misma función de vista en múltiples ramas de una definición de función o una expresión caso (por ejemplo, en size arriba), GHC intenta recoger estas aplicaciones en una sola expresión de caso anidado, de modo que la función de vista solo se aplica una vez. La compilación de patrones en GHC sigue el algoritmo de matriz descrito en el Capítulo 4 de The Implementation of Functional Programming Languages. Cuando las filas superiores de la primera columna de una matriz son todos los patrones de vista con la expresión "igual" , estos patrones se transforman en un solo caso anidado . Esto incluye, por ejemplo, visión adyacentes patrones que se alinean en una tupla, como en

 
f ((view -> A, p1), p2) = e1 
f ((view -> B, p3), p4) = e2 

La noción actual de cuando dos expresiones vista patrón son "el mismo" es muy restringido: no es incluso completa igualdad sintáctica. Sin embargo, sí incluye variables, literales, aplicaciones y tuplas; , por ejemplo, dos instancias de view ("hi", "there") serán recopiladas. Sin embargo, la implementación actual no se compara hasta equivalencia alfa, por lo que dos instancias de (x, view x -> y) no se fusionarán.

- The GHC manual

En cuanto a su fragmento, el problema es que no se está compilando con la optimización; con ambos ghc -O y ghc -O2, la línea solo se imprime una vez.Eso es siempre la primera cosa a comprobar cuando se tienen problemas relacionados con el rendimiento cuando se utiliza GHC :)

(Por cierto, Debug.Trace le permite comprobar este tipo de cosas sin tener que escribir manuales unsafePerformIO hacks.)

+0

¿Es posible que GHC esté insertando evaluaciones de repuesto adicionales debido a performUnsafeIO? No te preocupes, lo usé solo para probar la función. – julkiewicz

+0

He agregado una muestra de código concreto. – julkiewicz

+0

@julkiewicz: He actualizado mi respuesta :) – ehird

Cuestiones relacionadas