Recientemente, estoy tratando de usar Haskell en algunos de mis sistemas de producción de casos reales. El sistema de tipos Haskell realmente me ofrece una gran ayuda. Por ejemplo, cuando me di cuenta de que necesitaba alguna función de tipo
f :: (Foldable t, Monad m) => ( a-> b -> m b) -> b -> t a -> m b
En realidad, hay funciones como foldM, foldlMy foldrM.
Sin embargo, lo que realmente me sorprendió es la definición de estas funciones, tales como:
foldlM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
foldlM f z0 xs = foldr f' return xs z0
where f' x k z = f z x >>= k
entonces la función f'debe ser de tipo:
f' :: a -> b -> b
según lo requerido por foldr, entonces bdebe ser amable *-> m *, por lo que toda la definición de foldlMpodría tener sentido.
Otro ejemplo incluye definiciones de liftA2y<*>
(<*>) :: f (a -> b) -> f a -> f b
(<*>) = liftA2 id
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x = (<*>) (fmap f x)
Probé algunas de mis propias soluciones antes de mirar el código fuente. Pero la brecha es tan grande que no creo que pueda encontrar esta solución, sin importar cuántas líneas de código escriba en el futuro.
Entonces mi pregunta es, qué tipo de conocimiento o qué rama matemática específica es necesaria para que alguien razone en un nivel tan altamente abstracto.
Sé que la teoría de categorías podría ofrecer algo de ayuda y he estado siguiendo esta gran conferencia durante mucho tiempo y todavía estoy trabajando en ello.
fuente

Respuestas:
En general, lógica, etc., me imagino. Pero también puedes aprenderlo haciéndolo. :) Con el tiempo notas algunos patrones, toma algunos trucos.
Me gusta esto
foldrcon un argumento extra. Algunos lo ven como plegado en funciones para que puedan combinarse.yid(que a veces son realmente<=<yreturn),A algunos les resulta más fácil entenderlo en términos sintácticos más simples, como
entonces, cuando
gno es estricto en su segundo argumento,spuede servir como un estado que se transmite desde la izquierda, aunque estemos doblando a la derecha, como un ejemplo.fuente
Entonces, la mejor manera de entenderlo es hacerlo. A continuación hay una implementación de
foldlMuso enfoldllugar defoldr. Es un buen ejercicio, pruébalo y luego ve a la solución que sugeriría. El ejemplo explica todo el razonamiento que he hecho para lograrlo, que podría ser diferente al suyo y podría ser parcial porque ya sabía sobre el uso de un acumulador de funciones.Paso 1 : tratemos de escribir
foldlMen términos defoldlAquí te das cuenta de que
f'es puro y necesitarías extraer el resultado defescribir coincidencia. La única forma de 'extraer' un valor monádico es con el>>=operador, pero dicho operador debe ajustarse inmediatamente después de su uso.Como conclusión: cada vez que termines me gustaría desenvolver completamente esta mónada , solo ríndete. No es el camino correcto
Paso 2 : Intentemos escribir
foldlMen términos de,foldlpero primero, usarlo[]como plegable, ya que es fácil de combinar patrones (es decir, en realidad no necesitamos usarfold)Ok, eso fue fácil. Vamos a comparar la definición con la
foldldefinición habitual para listas¡¡Frio!! Son más o menos lo mismo. El caso trivial es exactamente lo mismo. El caso recursivo es un poco diferente de bits, desea escribir algo más como:
foldlM' f (f z0 x) xs. Pero no se compila como en el paso 1, por lo que puede pensar que está bien, no quiero aplicarf, solo para mantener dicho cálculo y componerlo>>=. Me gustaría escribir algo más comofoldlM' f (f z0 x >>=) xssi tuviera sentido ...Paso 3 Date cuenta de que lo que quieres acumular es una composición de funciones y no un resultado. ( Aquí probablemente soy parcial por el hecho de que ya lo sabía porque lo has publicado ).
Por el tipo
initFuncy el uso de nuestro conocimiento del paso 2 (la definición recursiva) podemos deducir esoinitFunc = return. La definición def'se puede completar sabiendo quef'debe usarfy>>=.Como puede ver, no es tan difícil hacerlo. Necesita práctica, pero no soy un desarrollador profesional de haskell y podría hacerlo yo mismo. Es una cuestión de práctica.
fuente
Monadcasos típicos .No necesitas ningún conocimiento específico en matemáticas para escribir una función como
foldM. Estoy usando Haskell en producción durante 4 años, y también estoy luchando por comprender esta definición defoldM. Pero eso se debe principalmente a que está mal escrito. Por favor, no lo tome como una falta personal si no puede entender algún código oscuro. Aquí hay una versión más legible defoldlMEsta función aún no es la más fácil. Principalmente porque tiene un uso no típico de
foldrdonde el acumulador intermedio es una función. Pero puede ver algunos mays que hacen que dicha definición sea más legible:where(para que conozca la forma de los argumentos).Después de ver dicha función, ahora puede realizar una técnica de razonamiento equitativo para expandir la definición paso a paso y ver cómo funciona. La capacidad de crear tales funciones viene con experiencia. No tengo habilidades matemáticas fuertes, y esta función no es una función típica de Haskell. Pero cuanto más práctica tengas, mejor se pone :)
fuente