Как разделить состояние между двумя монадами? - PullRequest
0 голосов
/ 04 ноября 2011

Я застрял со следующей проблемой монады:

Допустим, у меня есть стандартное состояние монады с состоянием S = (LS, RS). У меня также есть другая монада:

newtype StateP a = StateP {runP :: S -> (a, RS)}

Я хочу выполнить некоторые вычисления с использованием StateP, а затем объединить состояние с состоянием в монаде состояния:

merge m :: StateP() -> State()
merge m = do
 s@(l,r) <- get
 put (l, snd (runP m s))

Это не работает, но я не понимаю, почему? Есть ли другой способ добиться такой функциональности?

Ответы [ 3 ]

2 голосов
/ 04 ноября 2011

Если ваш код почти верен, попробуйте

merge :: StateP() -> State()
merge m = do
    s@(l,r) <- get
    put (l, snd (runP m s))

Но вы должны дать нам больше подробностей.

1 голос
/ 04 ноября 2011

Вы можете использовать монадные преобразователи для более точного моделирования этих требований, используя два стека монад: один, который может только читать LS, и другой, который может как читать, так и писать LS.

type ReadOnlyLS a  = ReaderT LS (State RS) a
type ReadWriteLS a = StateT LS (State RS) a

Чтобы запустить ReadOnlyLS в пределах ReadWriteLS, нам просто нужно извлечь LS из самого внешнего уровня состояний, передать его на уровень считывателя внутренних вычислений и перенести полученное вычисление обратно во внешнюю монаду:

merge :: ReadOnlyLS a -> ReadWriteLS a
merge m = get >>= lift . runReaderT m
0 голосов
/ 04 ноября 2011

Как вы достигаете функциональности RunP?Вы переопределяете экземпляр монады для него и получаете getP / putP?Ваш код выглядит нормально, можете ли вы предоставить m, который вы используете?Какое плохое поведение вы получаете?

...