Me gustaría tener una función como:¿Hay alguna forma sensata de descomprimir la mónada de estado?
unzipState :: (MonadState s m) => m (a, b) -> (m a, m b)
que tendría un cálculo (stateful) que devuelve una tupla, y volvería dos cálculos (dependientes).
La dificultad está, por supuesto, en que la extracción de valores de uno u otro cálculo debe actualizar el estado en el otro.
Un útil (y motivador) aplicación es la mónada aleatoria, expresado como
{-# LANGUAGE Rank2types #-}
import qualified System.Random as SR
import Control.Monad.State
type Random a = forall r. (State RandomGen r) => State r a
Y digamos que usted tiene:
normal :: Random Double
-- implementation skipped
correlateWith :: Double -> Random (Double, Double) -> Random (Double, Double)
correlateWith rho w = do
(u, v) <- w
return $ (u, p * u + (1 - p * p) * v)
sería muy natural a ser capaz de escribir:
let x = normal
y = normal
(u, v) = unzipState $ correlateWith 0.5 $ liftM2 (,) x y
... now I am able to perform computation on u and v as correlated random variables
¿Hay una manera sensata de hacerlo? Luché un poco, pero no logré llegar a nada. Hoogle tampoco fue de ayuda.
edición
Grandes respuestas me han mostrado mi problema está mal definido. Sin embargo, ¿alguien me puede explicar por qué la siguiente implementación en python (que creo que es correcta, pero no he probado mucho) no se puede traducir en Haskell (con la magia de STrefs, cierres y otras cosas, admito que no comprensión ;-)):
def unzipState(p):
flist, glist = [], []
def f(state):
if not flist:
(fvalue, gvalue), newstate = p(state)
glist.insert(0, gvalue)
return (fvalue, newstate)
else:
fvalue = flist.pop()
return (fvalue, state)
def g(state):
if not glist:
(fvalue, gvalue), newstate = p(state)
flist.insert(0, fvalue)
return (fvalue, newstate)
else:
gvalue = glist.pop()
return (gvalue, state)
return (f, g)
no es que yo estoy diciendo que el código de estado se puede traducir en Haskell, pero me siento como la comprensión qué y cuando (incluso en un ejemplo) que no se puede hacer lo haría mejorar mi comprensión mucho.
Edit2
Ahora bien, es claro como el cristal. Las funciones f y g obviamente no son puras, ya que su salida no depende únicamente del valor del estado.
¡Gracias nuevamente!
No creo que (Random a) realmente se pueda interpretar como distribuciones de probabilidad porque en ese caso, debe ser capaz de definir omega como un espacio probalizado, lo cual es bastante difícil. Además, no es porque los dos objetos de Random a tengan la misma distribución que son iguales (toma dos u = uniforme; v = uniforme, no tienes u = v). Una interpretación más humilde es entenderla como realizaciones (más específicamente, como funciones que operan en realizaciones) de variables aleatorias, que deberían ser isomórficas para las transmisiones, por lo que creo que la operación de descompresión está bien definida). – LeMiz
No. Si 'u = uniform :: Random A' y' v = uniform :: Random A', entonces es trivialmente cierto que 'u = v = uniform'. Tenga en cuenta que aquí hay dos nociones diferentes: variables aleatorias derivadas de un espacio de muestra Ω y colecciones de valores de tipo 'a' ponderados con una probabilidad (= distribución de probabilidad). Su mónada 'Random a' corresponde a la última, no a la primera. También es posible implementarlo como 'Random a = [(a, Probability)]'. [Me temo que es un poco complicado discutir esto sin una formalización de la mónada 'Random a' y el efecto particular que estás buscando.] –
estás perfectamente en el punto de igualdad, estaba confundido. Gracias ! – LeMiz