Estoy escribiendo un código (una muestra MCMC de Metropolis-Hastings) que utilizará un generador de números aleatorios y modificará una matriz y potencialmente otras estructuras basadas en esto.¿Una buena manera de realizar un seguimiento de varias referencias entre funciones en ST monad?
Mi idea inicial era usar la mónada ST, para poder usar las matrices ST y el paquete mersenne-random-pure64, manteniendo el generador PureMT como parte del estado.
Sin embargo, quiero poder separar parte del trabajo en funciones auxiliares separadas (por ejemplo, muestrear un entero aleatorio en un rango determinado, actualizar la estructura de la matriz y cosas potencialmente más complicadas). Para hacer esto, creo que necesitaría pasar las referencias al generador de PureMT y la matriz a todas las funciones, lo que rápidamente podría volverse muy feo si necesito almacenar más estado.
Mi instinto es agrupar todo el estado en un único tipo de datos al que pueda acceder en cualquier lugar, como usaría la mónada de estado definiendo un nuevo tipo de datos, pero no sé si eso es posible con el ST mónada, o la forma correcta de hacerlo.
¿Hay algún patrón agradable para hacer este tipo de cosas? Quiero mantener las cosas lo más generales posible, porque probablemente necesite agregar un estado extra y construir más código monádico alrededor de las partes existentes.
He intentado buscar ejemplos de código de mónada de ST, pero no parece estar cubierto en Real World Haskell, y los ejemplos de wiki de haskell son muy breves y simples.
gracias!
Esto suena como una buena idea, olvidé que las referencias no están cambiando. ¡Gracias por esto! También me pregunto sobre el posible uso de la mónada de ST desde dentro de sí misma para separar cálculos estatales independientes que se ejecutan en un entorno de nivel superior al que no necesitan acceder, con su propio estado local oculto. ¿Tendría que usar el transformador de mónada ST para esto, o puede simplemente usar let a = runST $ .... dentro de la mónada ST? Si puede (sin usar el transformador), ¿qué pasaría si tratara de desreferenciar una referencia de la mónada adjunta (suponiendo que estarían dentro del alcance)? – Tom
@Tom: no hay transformador para 'ST', como' IO', siempre está en la parte inferior de cualquier pila. Además, dos cómputos completos de 'ST', es decir, cosas que suceden dentro de una llamada a' runST', están completamente aislados del estado de cada uno, y cualquier intento de mezclarlos dará un error de tipo. Puede pasar valores opacos, tal como podría pasar 'IORef' dentro de' ST', pero tampoco puede * usar * ellos como tampoco podría usar 'IORef's. Sin embargo, puedes usar 'runST' como siempre; el resultado de eso es un valor puro, como siempre. –
@Tom: Además, si utiliza un 'ReaderT' como en mi ejemplo, probablemente podría implementar varios tipos de operaciones de horquillado sin demasiados problemas: clonando el entorno actual para ejecutarlo en un' ST' interno separado, ejecutando algo en el mismo 'ST' con un entorno diferente, & c. –