superior orden multiplos listas funciones funcion ejercicios ejemplos contador composicion ciclos haskell filter fold equational-reasoning

orden - haskell ejemplos



¿Estoy usando el razonamiento de sonido ecuacional sobre una definición de filtro en términos de foldr? (3)

A primera vista, los pasos que ha tomado en su ejemplo específico se ven correctos individualmente. Sin embargo, me gustaría señalar que tanto el filter como el foldr pueden aplicarse de manera útil a listas infinitas, lo que debería indicar que el orden de los pasos es incorrecto en lo que respecta a Haskell.

bueno, esta es la definición de la función de filtro usando foldr:

myFilter p xs = foldr step [] xs where step x ys | p x = x : ys | otherwise = ys

así que, por ejemplo, digamos que tengo esta función:

myFilter odd [1,2,3,4]

Así será:

foldr step [] [1,2,3,4]

y esto será

step 1 (foldr step [] [2,3,4])

y esto será

step 1 (step 2 (foldr step [] [3,4]))

y esto será

step 1 (step 2 (step 3 (foldr step [] [4])))

y esto será

step 1 (step 2 (step 3 (step 4 (foldr step [] []))))

y foldr step [] [] es [] así que:

step 1 (step 2 (step 3 (step 4 [])))

ahora entraremos en la función de step .
Aquí está la definición de step dentro de la función myFilter , desde arriba:

step x ys | p x = x : ys | otherwise = ys

también, te recuerdo que p es realmente la función odd en nuestro ejemplo.

Bueno, de nuevo, estamos aquí:

step 1 (step 2 (step 3 (step 4 [])))

y

x = 4 en el step más interno, y 4 no es impar, entonces ys , que es []

así que ahora tenemos esto:

step 1 (step 2 (step 3 []))

ahora, en el step más interno, x = 3 y 3 es impar, entonces devolvemos x:ys , que es 3 : [] , que es [3] , y ahora obtenemos:

step 1 (step 2 [3])

y ahora, en el step interno, x = 2 y 2 no es impar, entonces devolvemos ys , que es [3] , así que ahora obtendremos:

step 1 [3]

y ahora, x = 1 , y 1 es impar, entonces devolvemos x : ys , que es 1 : [3] , que es [1,3] .

El fin :-).

estoy en lo cierto en todos mis movimientos?
muchas gracias :-).

ps la definición de myFilter proviene del libro Real World Haskell , en el capítulo 4.


Esto me parece bien en la primera lectura.

Sin embargo, lo importante es recordar que para lograr una evaluación perezosa, Haskell realmente verá las cosas de otra manera. En otras palabras, la secuencia real se parece más a

step 1 (step 2 (step 3 (step 4 [])))

se convierte

step 1 <block1>

que se convierte

[1, <block1>]

entonces, si tratas de sacar el siguiente elemento de esa lista, se evaluará

[1, step 2 <block2>]

que se convierte

[1, <block2>]

y luego tratando de evaluar

[1, step 3 (step 4 [])]

se convierte en

[1, step 3 <block3>]

que se convierte

[1, 3, <block3>]

Esto me llevó un tiempo entenderlo. Era contradictorio para mí que, dado que foldr parece ser evaluado desde el "adentro hacia afuera", pero foldl se evalúa desde el "afuera en" que foldr sería flojo (lo cual es), mientras que foldl es estricto. Pero si lo piensas de la manera que describí arriba, tiene sentido (para mí, de todos modos).


Solo para ampliar el orden de evaluación diferida: básicamente, Haskell siempre evalúa la función primero, sin mirar los argumentos hasta que no tenga que hacerlo.

Si se utiliza el resultado de la llamada a myFilter (por ejemplo, impreso), la función se evaluará en el siguiente orden:

myFilter odd [1,2,3,4]

Primero se myFilter función myFilter :

foldr step [] [1,2,3,4]

Ahora foldr es la función más externa y se evalúa:

step 1 (foldr step [] [2,3,4])

Ahora el step se evalúa produciendo un 1 , ya que 1 es impar:

1 : foldr step [] [2,3,4]

Ahora, el primer elemento de la lista de resultados está disponible y puede ser utilizado por la función de llamada. Si la función de llamada también utiliza los siguientes elementos, la evaluación continúa con el foldr :

1 : step 2 (foldr step [] [3,4])

La evaluación del step ahora no produce ningún elemento nuevo, ya que 2 es par:

1 : foldr step [] [3,4]

Entonces foldr nuevamente:

1 : step 3 (foldr step [] [4])

Ahora el step evaluación produce 3 :

1 : 3 : foldr step [] [4]

Evaluando foldr ;

1 : 3 : step 4 (foldr step [] [])

Y step una vez más:

1 : 3 : foldr step [] []

Finalmente foldr evalúa a una lista vacía:

1 : 3 : []