Lema: Suponiendo equivalencia eta tenemos eso (\x -> ⊥) = ⊥ :: A -> B
.
Prueba: ⊥ = (\x -> ⊥ x)
por equivalencia eta y (\x -> ⊥ x) = (\x -> ⊥)
por reducción bajo la lambda.
El informe Haskell 2010, sección 6.2 especifica la seq
función mediante dos ecuaciones:
seq :: a -> b -> b seq ⊥ b = ⊥ seq ab = b, si a ≠ ⊥
Luego afirma "Como consecuencia, ⊥ no es lo mismo que \ x -> ⊥, ya que seq puede usarse para distinguirlos".
Mi pregunta es, ¿es realmente una consecuencia de la definición de seq
?
El argumento implícito parece ser que seq
sería indiscutible si seq (\x -> ⊥) b = ⊥
. Sin embargo, no he podido demostrar que tal seq
sería indiscutible. Me parece que seq
es monótono y continuo, lo que lo pone en el ámbito de ser computable.
Un algoritmo que se implemente, como seq, podría funcionar al intentar buscar algún x
lugar f x ≠ ⊥
enumerando el dominio que f
comienza con ⊥. Aunque tal implementación, incluso si es posible, se vuelve bastante complicada una vez que queremos hacer seq
polimórficos.
¿Hay alguna prueba de que no hay computable seq
que se identifica (\x -> ⊥)
con el ⊥ :: A -> B
? Alternativamente, ¿hay algo de construcción del seq
que se identifica (\x -> ⊥)
con el ⊥ :: A -> B
?
fuente
seq
seq
Tenga en cuenta que la especificación para la
seq
que cita no es su definición. Para citar el informe Haskell "La función seq está definida por las ecuaciones : [y luego las ecuaciones que usted da]".Tal comportamiento violaría la especificación de
seq
.Es importante destacar que, dado que
seq
es polimórfico,seq
no se puede definir en términos de deconstructores (proyecciones / coincidencia de patrones, etc.) en ninguno de los dos parámetros.Si
seq' (\x -> ⊥) b
, uno podría pensar que podríamos aplicar el primer parámetro (que es una función) a algún valor y luego sacar ⊥. Pero,seq
nunca puede identificar el primer parámetro con un valor de función (incluso si resulta ser uno para algún usoseq
) debido a su tipo polimórfico paramétrico. La parametricidad significa que no sabemos nada sobre los parámetros. Además,seq
nunca puede tomar una expresión y decidir "¿es esto ⊥?" (cf. el problema de detención),seq
solo puede intentar evaluarlo y divergir a ⊥.Lo que
seq
hace es evaluar el primer parámetro (no completamente, sino en "forma normal de cabeza débil" [1], es decir, en el constructor superior), luego devolver el segundo parámetro. Si el primer parámetro resulta ser⊥
(es decir, un cálculo que no termina), entonces evaluarlo haceseq
que no termine, y asíseq ⊥ a = ⊥
.[1] Teoremas libres en presencia de seq - Johann, Voigtlander http://www.iai.uni-bonn.de/~jv/p76-voigtlaender.pdf
fuente
f : forall a . a -> T
(dondeT
es algún otro tipo), entoncesf
no puede aplicar ningún deconstructor a su primer argumento, ya que no sabe qué deconstructores aplicar. No podemos hacer un "caso" sobre los tipos. He tratado de mejorar la respuesta anterior (incluida la información sobre laseq
evaluación de la forma normal de la cabeza).Samson Abramsky consideró este tema hace mucho tiempo y escribió un artículo llamado " El cálculo perezoso de Lambda ". Entonces, si quieres definiciones formales, aquí es donde puedes mirar.
fuente
Demostrando que λ x. Ω ≠ Ω es uno de los objetivos que Abramsky establece para su teoría del cálculo perezoso lambda (página 2 de su artículo , ya citado por Uday Reddy), porque ambos están en forma normal de cabeza débil. A partir de la definición 2.7, discute explícitamente que eta-reducción λ x. M x → M no es generalmente válido, pero es posible si M termina en todos los entornos. Esto no significa que M debe ser una función total, solo que la evaluación de M debe terminar (reduciéndose a una lambda, por ejemplo).
Su pregunta parece estar motivada por preocupaciones prácticas (rendimiento). Sin embargo, aunque el Informe Haskell podría ser menos que completamente claro, dudo que iguale λ x. ⊥ with ⊥ produciría una implementación útil de Haskell; si implementa Haskell '98 o no es discutible, pero dado el comentario, está claro que los autores pretendieron que fuera así.
Finalmente, ¿cómo seq para generar elementos para un tipo de entrada arbitraria? (Sé que QuickCheck define la clase de tipo Arbitraria para eso, pero no está permitido agregar tales restricciones aquí). Esto viola la parametricidad.
Actualizado : no logré codificar esto correctamente (porque no soy tan fluido en Haskel), y arreglar esto parece requerir
runST
regiones anidadas . Intenté usar una sola celda de referencia (en la mónada ST) para guardar tales elementos arbitrarios, leerlos más tarde y hacerlos disponibles universalmente. La parametricidad demuestra que abreak_parametricity
continuación no se puede definir (excepto al regresar al fondo, por ejemplo, un error), mientras que podría recuperar los elementos que generaría la secuencia propuesta.Tengo que admitir que estoy un poco confuso en formalizar la prueba de parametricidad necesaria aquí, pero este uso informal de la parametricidad es estándar en Haskell; pero aprendí de los escritos de Derek Dreyer que la teoría necesaria se está resolviendo rápidamente en estos últimos años.
EDICIONES:
fuente
(\x -> writeSTRef cell (Just x) >> return x)
en entradas aleatorias no ejecuta una escritura en la celda. SolorunST
se ejecutan los comandos ST que entran en la secuencia que se pasa . Del mismo modo, la ejecuciónmain = (putStrLn "Hello") `seq` (return ())
no imprime nada en la pantalla.