Я бы хотел иметь такую функцию, как:
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 не являются чистыми, поскольку их результат зависит не только от значения состояния.
Еще раз спасибо!