haskell - sitename - ¿Qué sucede con las variables de tipo faltantes en el núcleo de estilo de la Iglesia?
yoast short description (2)
Aquí está el núcleo generado por GHC (después de agregar algunos NOINLINE
NOINLINE).
qoo_rbu :: forall a_abz. (a_abz -> a_abz) -> GHC.Base.String
[GblId, Arity=1, Caf=NoCafRefs]
qoo_rbu = / (@ a_abN) _ -> GHC.Types.[] @ GHC.Types.Char
poo_rbs :: forall a_abA. GHC.Base.String -> a_abA -> a_abA
[GblId, Arity=1]
poo_rbs = / (@ a_abP) _ -> GHC.Base.id @ a_abP
roo_rbw :: GHC.Base.String -> GHC.Base.String
[GblId]
roo_rbw =
GHC.Base..
@ (GHC.Prim.Any -> GHC.Prim.Any)
@ GHC.Base.String
@ GHC.Base.String
(qoo_rbu @ GHC.Prim.Any)
(poo_rbs @ GHC.Prim.Any)
Parece que GHC.Prim.Any
se utiliza para el tipo polimórfico.
De los documentos (énfasis mío):
El constructor de tipos
Any
es un tipo al que puede obligar de forma poco segura cualquier tipo levantado, y viceversa.
- Es levantado, y por lo tanto representado por un puntero.
- No pretende ser un tipo de datos, y eso es importante para el generador de código, ya que el código gen puede ingresar un valor de datos pero nunca ingresa un valor de función.
También se usa para instanciar variables de tipo sin restricciones después de la verificación de tipos.
Tiene sentido tener un tipo de este tipo para insertar en lugar de tipos sin restricciones, ya que de lo contrario las expresiones triviales como la length []
podrían causar un error de tipo ambiguo.
Esto es un poco esotérico, pero enloquecedor. En respuesta a otra pregunta , noté que en este programa completamente válido
poo :: String -> a -> a
poo _ = id
qoo :: (a -> a) -> String
qoo _ = ""
roo :: String -> String
roo = qoo . poo
La variable de tipo a
no se resuelve ni se generaliza en el proceso de verificación de roo
. Me pregunto qué pasará con la traducción al lenguaje central de GHC, una variante del Sistema F al estilo de la Iglesia. Permítanme explicar las cosas a mano, con el tipo explícito lambdas //
y aplicaciones de tipo @
.
poo :: forall a. [Char] -> a -> a
poo = // a -> / s x -> id @ a
qoo :: forall a. (a -> a) -> [Char]
qoo = // a -> / f -> [] @ Char
roo :: [Char] -> [Char]
roo = (.) @ [Char] @ (? -> ?) @ [Char] (qoo @ ?) (poo @ ?)
¿Qué diablos pasa en el ?
lugares ¿Cómo se convierte roo
en un término central válido? ¿O realmente obtenemos un misterioso cuantificador de vacío, a pesar de lo que dice la firma de tipo?
roo :: forall a. [Char] -> [Char]
roo = // a -> ...
Acabo de comprobar que
roo :: forall . String -> String
roo = qoo . poo
pasa por ok, lo que puede significar o no que la cosa se compruebe sin cuantificación adicional.
¿Qué está pasando ahí abajo?
Esto no es un problema. En la firma de roo , la variable de tipo a simplemente no aparece como está. Un ejemplo más fácil sería la expresión.
const 1 id
dónde
id :: forall a.a->a