tipos reservadas palabras opciones mundo listas imprimir hola hacer ejemplos datos como haskell where

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.