reservadas - string en haskell
¿Hay algo en la cláusula ''dónde'' en Haskell que solo se calcula una vez? (3)
La respuesta de Carsten (el valor se computará a lo sumo una vez) es correcta siempre y cuando no haya desactivado la restricción de monomorfismo. Si lo ha hecho, entonces m
podría tener un tipo inferido polimórfico que involucra una clase de tipo, y luego m
no es realmente un valor normal, sino una función que toma un diccionario de clase de tipo y produce un valor. Considera este ejemplo.
{-# LANGUAGE NoMonomorphismRestriction #-}
import Debug.Trace(trace)
func n = m ++ [1] ++ m ++ [0] ++ m
where m = func2 n -- m :: Monad t => t a (where n :: a)
func2 n = trace "called..." (return n) -- func2 :: Monad t => a -> t a
Luego evaluando func 3
en impresiones ghci
called...
[3,1called...
,3,0called...
,3]
Cuando tenga el siguiente código:
func n = m ++ [1] ++ m ++ [0] ++ m
where m = func2 n
¿Cuántas veces se llama la función func2? Sólo una vez, en la cláusula de dónde? ¿O simplemente se calcula de nuevo cada vez que uso m?
Para agregar a las respuestas de @ Carstan y @Reid Barton, también depende de si está ejecutando o no el código compilado, por ejemplo:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Debug.Trace(trace)
func n = m ++ [1] ++ m ++ [0] ++ m
where m = func2 n -- m :: Monad t => t a (where n :: a)
func2 n = trace "called..." (return n)
main = let xs = func 3 :: [Int]
in print xs
En ghci
ejecutan las impresiones main
called
3 veces. Sin embargo, cuando se compila, solo se imprime una vez cuando se usa -O2
. (Probado con 7.10.2.)
Tal vez no se haya evaluado en absoluto (la alegría de la pereza), pero si lo está, solo debería evaluarse una vez; si lo desea, puede intentarlo usted mismo con una trace
:
import Debug.Trace(trace)
func n = m ++ [1] ++ m ++ [0] ++ m
where m = func2 n
func2 n = trace "called..." [n]
Aquí hay un ejemplo en GHCi:
λ> func 3
called...
[3,1,3,0,3]
Y aquí es donde ves que podría no ser llamado (hasta que finalmente necesites evaluarlo):
λ> let v = func 4
λ> v
called...
[4,1,4,0,4]
Consulte: al principio no se llama, solo cuando finalmente evalúa v
(para imprimirlo) recibe la llamada.