Question

I am stuck with following monad problem:

Let's say I have a standard monad State with state S = (LS, RS). I also have another monad:

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

I want to perform some computation using StateP then merge state with state in State monad:

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

It is not working, but I don't get why? Is there another way to achieve such functionality?

Was it helpful?

Solution

You can use monad transformers to model these requirements more explicitly using two monad stacks: one that can only read LS and one that can both read and write LS.

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

To run a ReadOnlyLS within ReadWriteLS, we just need to extract LS from the outermost state layer, give it to the reader layer of the inner computation and lift the resulting computation back into the outer monad:

merge :: ReadOnlyLS a -> ReadWriteLS a
merge m = get >>= lift . runReaderT m

OTHER TIPS

On the off-chance that your code is nearly right, try

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

But you need to give us more details really.

How do you achieve the functionality of RunP? Do you redefine a monad instance for it and have getP/putP? Your code seems fine, can you provide the m you use? What kind of misbehaviour do you get?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top