Мне бы хотелось иметь такую функцию:
unzipState :: (MonadState s m) => m (a, b) -> (m a, m b)
, которая бы выполняла (с сохранением состояния) вычисления, которые возвращали бы кортеж, и возвращала бы два (зависимых) вычисления.
Сложность, конечно, заключается в том, что извлечение значений из одного или другого вычисления должно обновлять состояние в другом.
Полезным (и мотивирующим) приложением является случайная монада, выраженная как
{-# LANGUAGE Rank2types #-}
import qualified System.Random as SR
import Control.Monad.State
type Random a = forall r. (State RandomGen r) => State r a
и скажем, у вас есть:
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)
было бы вполне естественно иметь возможность написать:
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
Есть ли разумный способ сделать это?Я немного боролся, но не смог добраться ни к чему.Hoogle тоже не помог.
edit
Отличные ответы показали, что моя проблема плохо определена.Тем не менее, кто-то может объяснить мне , почему следующая реализация в python (которую я считаю правильной, но не очень много проверенной) не может быть переведена в Haskell (с магией STrefs, замыканий и других вещей, которые я допускаюЯ не понимаю ;-)):
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)
Не то чтобы я говорил, что код с сохранением состояния может быть переведен в Haskell, но мне хочется понять , почему и , когда (даже на примере) это невозможно сделать, это сильно улучшило бы мое понимание.
edit2
Теперь это кристально ясно.Функтоны f и g, очевидно, не являются чистыми, поскольку их вывод зависит не только от значения состояния.
Еще раз спасибо!