Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 959483
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 16, 20262026-05-16T01:02:12+00:00 2026-05-16T01:02:12+00:00

I finally got a hold on how to use monads (don’t know if I

  • 0

I finally got a hold on how to use monads (don’t know if I understand them…), but my code is never very elegant. I guess is from a lack of grip on how all those functions on Control.Monad can really help. So I’d thought it would be nice to ask for tips on this in a particular piece of code using the state monad.

The goal of the code is to calculate many kinds of random walks, and it’s something I’m trying to do before something more complicated. The problem is that I have two stateful computations at the same time, and I’d like to know how to compose them with elegance:

  1. The function that updates the random number generator is something of type Seed -> (DeltaPosition, Seed)
  2. The function that updates the position of the random walker is something of type DeltaPosition -> Position -> (Log, Position) (where Log is just some way for me to report what is the current position of the random walker).

What I’ve done is this:

I have a function to compose this two stateful computations:

composing :: (g -> (b, g)) -> (b -> s -> (v,s)) -> (s,g) -> (v, (s, g))
composing generate update (st1, gen1) = let (rnd, gen2) = generate gen1
                                            (val, st2)  = update rnd st1
                                        in (val, (st2, gen2))

and then I turn it into a function that compose states:

stateComposed :: State g b -> (b -> State s v) -> State (s,g) v
stateComposed rndmizer updater = let generate = runState rndmizer
                                     update x = runState $ updater x
                                 in  State $ composing generate update 

And then I have the simplest thing, for example, a random walker that will just sum a random number to its current position:

update :: Double -> State Double Double
update x = State (\y -> let z = x+y
                        in  (z,z))

generate :: State StdGen Double
generate = State random

rolling1 = stateComposed generate update 

and a function to do this repeatedly:

rollingN 1 = liftM (:[]) rolling1
rollingN n = liftM2 (:) rolling1 rollings
    where rollings = rollingN (n-1) 

And then, if I load this in ghci and run:

*Main> evalState (rollingN 5) (0,mkStdGen 0)
[0.9872770354820595,0.9882724161698186,1.9620425108498993,2.0923229488759123,2.296045158010918]

I get what I want, which is a list of the positions occupied by the random walker. But… I feel there must be a more elegant way to do this. I have two questions:

  1. Can I rewrite those functions in a more “monadic” way, using clever functions from Control.Monad?

  2. Is there a general pattern about combining states like this that can be used? Does this have something to do with monad transformers or something like that?

  • 1 1 Answer
  • 1 View
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-16T01:02:13+00:00Added an answer on May 16, 2026 at 1:02 am

    Update: I should have mentioned that there’s actually a much nicer way to do this that doesn’t require State or monads at all:

    takeStep :: (Double, StdGen) -> (Double, StdGen)
    takeStep (p, g) = let (d, g') = random g in (p + d, g')
    
    takeSteps n = take n . tail . map fst $ iterate takeStep (0, mkStdGen 0)
    

    It works as desired:

    *Main> takeSteps 5
    [0.9872770354820595,0.9882724161698186,1.9620425108498993,2.0923229488759123,2.296045158010918]
    

    If you’re not committed to the idea of “composing” two separate stateful computations, you can accomplish the same thing much more straightforwardly:

    takeStep :: State (Double, StdGen) Double
    takeStep = do
      (pos, gen) <- get
      let (delta, gen') = random gen
      let pos' = pos + delta
      put (pos', gen')
      return pos'
    
    takeSteps n = evalState (replicateM n takeStep) (0, mkStdGen 0)
    

    This produces the same output as your example:

    *Main> takeSteps 5
    [0.9872770354820595,0.9882724161698186,1.9620425108498993,2.0923229488759123,2.296045158010918]
    

    This approach (doing all the state manipulation in a single monad instead of trying to compose a State A and State B) seems to me like the most elegant solution.


    Update: To answer your question about using monad transformers to stack State monads: it’s certainly possible. We can write the following, for example:

    update' :: (Monad m) => Double -> StateT Double m Double
    update' x = StateT $ \y -> let z = x + y in return (z, z)
    
    generate' :: (Monad m) => StateT StdGen m Double
    generate' = StateT $ return . random
    
    takeStep' :: StateT Double (State StdGen) Double
    takeStep' = update' =<< lift generate'
    
    takeSteps' n = evalState (evalStateT (replicateM n takeStep') 0) $ mkStdGen 0
    

    We could also do the stacking in the opposite order.

    This version again produces the same output, but in my opinion the non-StateT version is a bit clearer.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I finally got some parts working here: http://jsfiddle.net/trXBr/5/ but when I put the code
I finally got my code to reference the ruby-alsa library , but I'm stuck
So I finally got my boss to approve the use of perl for this
Alright, I finally got this code to work after hours of toiling: Dim path
Hi I've finally got Suckerfish working and styled but in IE7 it is hidden
I finally got myself to look at some Linux code. I am looking right
I finally got my app to be able to send text messages (SMS), but
I finally got a section of my code to run in parallel with OpenMP
I finally got some understanding of how Ninject handles DI, but have faced the
I finally got the password, the queries, the button and the connection, but how

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.