Es difícil agregar algo a las explicaciones de Andrej o Neel, pero lo intentaré. Voy a tratar de abordar el punto de vista sintáctico, en lugar de tratar de descubrir la semántica subyacente, porque la explicación es más elemental y puedo dar una respuesta más directa a su pregunta.
λ
La referencia crucial es la siguiente:
Mendler, N. (1991). Tipos inductivos y restricciones de tipo en el cálculo lambda de segundo orden. No he encontrado una referencia en línea, me temo. Sin embargo, las declaraciones y pruebas se pueden encontrar en la tesis doctoral de Nax (¡una lectura muy recomendable!).
Bad
Bad=Bad→A
A
λx:Bad.x x:Bad→A
y entonces
(λx:Bad.x x) (λx:Bad.x x):A
Bad=F(Bad)
F(X)XF(X)
Por supuesto, no está trabajando con tipos definidos equitativamente sino con constructores , es decir, tiene
data Bad = Pack (Bad -> A)
en lugar de estricta igualdad. Sin embargo, puedes definir
unpack :: Bad -> (Bad -> A)
unpack (Pack f) = f
lo cual es suficiente para que este resultado continúe siendo válido:
(\x:Bad -> unpack x x) (Pack (\x:Bad -> unpack x x))
A
En su segundo ejemplo, las cosas son un poco más complicadas, ya que tiene algo en la línea de
Bad=Bad′→A
Bad′BadBad aBad (Not a)
type Not a = a -> False
con
data Not a = Not a
Se resolvería fácilmente si Haskell permitiera tales definiciones de tipo:
type Acc = Not Acc
En este caso, podría construir un combinador de bucles exactamente de la misma manera que antes. Sospecho que puedes llevar una construcción similar (pero más compleja) usando
data Acc = D (Not Acc)
El problema aquí es que para construir un isomorfismo
Bad Acc <-> Bad (Not Acc)
tienes que lidiar con la varianza mixta.