write pagina oficial mac from cancel and haskell semantics lazy-evaluation evaluation

haskell - pagina - ¿Cómo funciona seq force?



vim pagina oficial (2)

Fondo

Esta pregunta surge de un desafío que Brent Yorgey planteó en OPLSS: escribe una función f :: (Int -> Int) -> Bool que distingue f undefined de f (/x -> undefined) . Todas nuestras respuestas utilizaron seq o algo así como patrones de explosión que desaparecen en seq . Por ejemplo:

f :: (Int -> Int) -> Bool f g = g `seq` True *Main> f undefined *** Exception: Prelude.undefined *Main> f (/x -> undefined) True

El comentario de GHC sobre seq dice que

e1 `seq` e2

solía desugar en

case e1 of { _ -> e2 }

Así que traté de desugaring manualmente. No funcionó:

f'' g = case g of { _ -> True } *Main> f'' undefined True *Main> f'' (/x -> undefined) True

Pregunta

¿Depende este comportamiento de la secuencia más compleja que se describe al final del comentario y, de ser así, cómo funciona? ¿Podría escribirse tal f sin estos primitivos?

x `seq` e2 ==> case seq# x RW of (# x, _ #) -> e2 -- Note shadowing! e1 `seq` e2 ==> case seq# x RW of (# _, _ #) -> e2


Hay una descripción de nivel más alto de la máquina STG en Cómo hacer un curry rápido: push / enter vs eval / apply

La figura 2 contiene la regla CASEANY que funciona para las funciones. En este documento, la proposición "es un valor" significa:

  • Es una aplicación constructora saturada.
  • es una funcion
  • es una aplicación de función parcial (que sigue siendo una función, semánticamente)

Los valores de Unboxed, incluidos los literales, se tratan de forma especial; se puede encontrar más información en los valores de Unboxed como ciudadanos de primera clase.

Todos estos son detalles de implementación y están ocultos dentro del compilador (GHC). La expresión de caso de Haskell no obliga a su escrutador, solo lo hacen los patrones y la secuencia.


seq no se puede implementar en Haskell. En su lugar, es un "gancho" primitivo en la evaluación a la forma normal de cabeza débil en cualquier tiempo de ejecución en el que se esté ejecutando Haskell. Por ejemplo, en GHC se compila a un case en GHC Core, que desencadena la evaluación al constructor más externo.

Como no se puede implementar en Haskell puro, se define (en GHC) como primop:

pseudoop "seq" a -> b -> b { Evaluates its first argument to head normal form, and then returns its second argument as the result. }

Dado que las funciones no tienen una forma normal, se detiene la evaluación una vez que alcanza una.

Mágicamente disponible para el compilador. Lo mismo ocurre con otras primitivas como par o unsafeCoerce , el token de RealWorld , forkOn , etc. Todas las cosas útiles.