En el recursion-schemespaquete se definen los siguientes tipos:
newtype Fix f = Fix (f (Fix f))
newtype Mu f = Mu (forall a. (f a -> a) -> a)
¿Son isomorfos? Si es así, ¿cómo lo demuestras?
En el recursion-schemespaquete se definen los siguientes tipos:
newtype Fix f = Fix (f (Fix f))
newtype Mu f = Mu (forall a. (f a -> a) -> a)
¿Son isomorfos? Si es así, ¿cómo lo demuestras?
Mu f < Fix f < Nu fFix-to-Mues esencialmentecata, mientras queMu-to-Fixesmu2fix (Mu x) = x Fix. La parte difícil es demostrar que estos son inversos mutuos, explotando la parametricidad.Fixque no es representableMu? ISTMFixdebería ser el más pequeño (intuitivamente porque es una "estructura de datos" y no puede contener fondos)Respuestas:
Sí, son isomórficos en Haskell. Vea ¿Cuál es la diferencia entre Fix, Mu y Nu en el paquete de esquema de recursión de Ed Kmett para algunos comentarios adicionales?
Comencemos definiendo funciones para realizar las conversiones:
Para mostrar que esas funciones son testigos de un isomorfismo, debemos mostrar que:
Desde
Fixy hacia atrásUna de las direcciones del isomorfismo es algo más directa que la otra:
El pasaje final anterior,
cata Fix t = tse puede verificar a través de la definición decata:cata Fix t, entonces, esFix (fmap (cata Fix) (unfix t)). Podemos usar la inducción para mostrar que debe sert, al menos para un finitot(se vuelve más sutil con estructuras infinitas; vea el apéndice al final de esta respuesta). Hay dos posibilidades a considerar:unfix t :: f (Fix f)está vacío, no tiene posiciones recursivas para cavar. En ese caso, debe ser igualfmap absurd zpara algunosz :: f Void, y por lo tanto:unfix tno está vacío. En ese caso, al menos sabemos quefmap (cata Fix)no puede hacer nada más que aplicarcata Fixen las posiciones recursivas. La hipótesis de inducción aquí es que hacerlo dejará esas posiciones sin cambios. Entonces tenemos:(En última instancia,
cata Fix = ides un corolario deFix :: f (Fix f) -> Fix xser un álgebra F inicial. Recurrir directamente a ese hecho en el contexto de esta prueba probablemente sería demasiado atajo).Desde
Muy hacia atrásDado
muToFix . fixToMu = id, para demostrar quefixToMu . muToFix = ides suficiente probar:eso
muToFixes inyectivo, oque
fixToMues sobreyectiva.Tomemos la segunda opción y revisemos las definiciones relevantes:
fixToMuser surjective, entonces, significa que, dado cualquier específicoFunctorf, todas las funciones de tipoforall a. (f a -> a) -> apueden definirse como\alg -> cata alg t, para algunos específicost :: Fix f. La tarea, entonces, se convierte en catalogar lasforall a. (f a -> a) -> afunciones y ver si todas ellas pueden expresarse de esa forma.¿Cómo podríamos definir una
forall a. (f a -> a) -> afunción sin apoyarnosfixToMu? No importa qué, debe implicar el uso delf a -> aálgebra suministrada como argumento para obtener unaresultado. La ruta directa lo estaría aplicando a algúnf avalor. Una advertencia importante es que, dado queaes polimórfico, debemos ser capaces de conjurar dichof avalor para cualquier elección dea. Esa es una estrategia factible siemprefque existan valores. En ese caso, podemos hacer:Para aclarar la notación, definamos un tipo de cosas que podemos usar para definir
forall a. (f a -> a) -> afunciones:Además de la ruta directa, solo hay otra posibilidad. Dado que
fes unFunctor, si de alguna manera tenemos unf (Moo f)valor, podemos aplicar el álgebra dos veces, la primera aplicación está debajo de lafcapa externa , víafmapyfromMoo:Teniendo en cuenta que también podemos hacer
forall a. (f a -> a) -> adef (Moo f)los valores, que tiene sentido para agregarlos como un caso deMoo:En consecuencia,
fromLayeredse puede incorporar afromMoo:Tenga en cuenta que, al hacerlo, hemos pasado furtivamente de la aplicación
algbajo unafcapa a la aplicación recursivaalgbajo un número arbitrario defcapas.A continuación, podemos observar
f Voidque se puede inyectar un valor en elLayeredconstructor:Eso significa que en realidad no necesitamos el
Emptyconstructor:¿Qué pasa con el
EmptycasofromMoo? La única diferencia entre los dos casos es que, en elEmptycaso, tenemos enabsurdlugar de\moo -> fromMoo moo alg. Como todas lasVoid -> afunciones sonabsurd, tampoco necesitamos unEmptycaso separado :Un posible ajuste cosmético es voltear los
fromMooargumentos, por lo que no necesitamos escribir el argumentofmapcomo lambda:O, más libre de puntos:
En este punto, una segunda mirada a nuestras definiciones sugiere que es necesario cambiar el nombre:
Y ahí está: todas las
forall a. (f a -> a) -> afunciones tienen la forma\alg -> cata alg tpara algunost :: Fix f. Por lo tanto,fixToMues surjective, y tenemos el isomorfismo deseado.Apéndice
En los comentarios, se planteó una pregunta pertinente sobre la aplicabilidad del argumento de inducción en la
cata Fix t = tderivación. Como mínimo, las leyes fundadoras y la paramétrica aseguran quefmap (cata Fix)no creará trabajo adicional (por ejemplo, no aumentará la estructura ni introducirá posiciones recursivas adicionales para profundizar), lo que justifica por qué entrar en las posiciones recursivas es todo lo que importa en el paso inductivo de la derivación. Siendo así, si settrata de una estructura finita, el caso base de un vacíof (Fix t)finalmente se alcanzará, y todo está claro.tSin embargo, si permitimos ser infinitos, podemos seguir descendiendo sin cesar,fmapdespuésfmapdespuésfmap, sin llegar nunca al caso base.Sin embargo, la situación con estructuras infinitas no es tan horrible como podría parecer al principio. La pereza, que es lo que hace viables las estructuras infinitas en primer lugar, nos permite consumir estructuras infinitas perezosamente:
Si bien la sucesión de posiciones recursivas se extiende infinitamente, podemos detenernos en cualquier punto y obtener resultados útiles de los
ListFcontextos funerarios circundantes . Tales contextos, vale la pena repetir, no se ven afectadosfmap, por lo que cualquier segmento finito de la estructura que podamos consumir no se verá afectadocata Fix.Este aplazamiento refleja cómo la pereza, como se menciona en esta discusión otra parte, la pereza colapsa la distinción entre los puntos fijos
Mu,FixyNu. Sin holgazanería,Fixno es suficiente para codificar una curión productiva y, por lo tanto, tenemos que cambiar alNumayor punto fijo. Aquí hay una pequeña demostración de la diferencia:fuente
cata Fix t = t? Asumir queFix fes el álgebra inicialfparece un poco un atajo. (La prueba vinculada a la respuesta relacionada parece evitar esto al usar la parametricidad en ambos sentidos.)fixToMula surjectivity. "si queremos definir un principio a. (fa -> a) -> una función desde cero" Eso no es lo que queremos. En cambio, vamosk :: forall a. (f a -> a) -> a, tenemos que mostrar esok = \alg -> cata alg tpara algunost.cata Fix, tenemoscata Fix = Fix . fmap (cata Fix) . unfix. Sitno tiene posiciones recursivas,fmap (cata Fix)no hará nada, y asícata Fix t = Fix (unfix t) = t. Si tiene posiciones recursivas, todofmap (cata Fix)lo que hará será aplicarlescata Fix, lo que parece suficiente para resolver el problema por inducción.kdebe obtenerse aplicando directamente el álgebra (para el quef Voidse necesita un valor) o utilizandofmappara aplicarlo recursivamente, y ambos casos pueden expresarse en la forma \ alg -> cata alg t`. Así que creo que he hecho lo que usted sugiere, aunque "desde cero" podría no haber sido la mejor opción de palabras para describirlo.cata Fix t = tderivación (de hecho, dadas las similitudes entre los dos argumentos, ahora siento que presentarlo ayuda a preparar el terreno para la segunda parte de la respuesta) . Gracias por resaltar esos puntos para mejorar.