On Mon, Jan 12, 2009 at 8:34 PM, Phil <pbeadl...@mail2web.com> wrote: > Thanks Minh - I've updated my code as you suggested. This looks better than > my first attempt! > > Is it possible to clean this up any more? I find: > > ( (), (Double, Word64) ) > > a bit odd syntactically, although I understand this is just to fit the type > to the State c'tor so that we don't have to write our own Monad longhand.
If you have a function which transforms the state, you can lift it into the state monad using "modify". > evolveUnderlying :: (Double, Word64) -> (Double, Word64) > evolveUnderlying (stock, state) = ( newStock, newState ) > where > newState = ranq1Increment state > newStock = stock * exp ( ( ir - (0.5*(vol*vol)) )*timeStep + ( > vol*sqrt(timeStep)*normalFromRngState(state) ) ) > > getEvolution :: State (Double, Word64) () > getEvolution = modify evolveUnderlying Now, I don't know the full context of what you're doing, but the example you posted isn't really gaining anything from the state monad. Specifically, execState (replicateM_ n (modify f)) = execState (modify f >> modify f >> ... >> modify f) = execState (modify (f . f . ... . f)) = f . f . ... . f So you could just write something along these lines, > mcSimulate :: Double -> Double -> Word64 -> [Double] > mcSimulate startStock endTime seedForSeed = fst expiryStock : mcSimulate > startStock endTime newSeedForSeed > where > expiryStock = iterate evolveUnderlying (startStock, ranq1Init seedForSeed) > !! truncate (endTime/timeStep) > newSeedForSeed = seedForSeed + 246524 Coming back to your original question, it is possible to work with nested state monad transformers. The trick is to use "lift" to make sure you are working with the appropriate state. get :: StateT s1 (State s2) s1 put :: s1 -> StateT s1 (State s2) () lift get :: StateT s1 (State s2) s2 lift put :: s2 -> StateT s1 (State s2) () A more general piece of advice is to try breaking things into smaller pieces. For example: getRanq1 :: MonadState Word64 m => m Word64 getRanq1 = do seed <- get put (ranq1Increment seed) return seed getEvolution :: StateT Double (State Word64) () getEvolution = do seed <- lift getRanq1 modify $ \stock -> stock * exp ( ( ir - (0.5*(vol*vol)) )*timeStep + ( vol*sqrt(timeStep)*normalFromRngState(seed) ) ) -- Dave Menendez <d...@zednenem.com> <http://www.eyrie.org/~zednenem/> _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe