Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A 'State' monad, and corresponding additions to the code by 'iitalic' #48

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

aaronmcdaid
Copy link

Maybe I've reinvented the wheel, but as an exercise here is an implemention of the State monad (state.rkt) with the relevant get, put and modify operations.

Also, based on that, I've added some relevant functions to random.rkt for drawing random numbers through State PRNG:

draw-double : (State PRNG Double)
draw-range : {Integer -> Integer -> (State PRNG Integer)}
draw-below : {Integer -> (State PRNG Integer)}

Demo of (State Integer):

(def stateInteger : (State Integer (List Integer))
  (do
    [i1 <- get]                  ; query the initial state
    (modify (+ 10))              ; modify the internal state, adding 10 to it
    [i2 <- get]                  ; query again
    (modify (+ 10))              ; modify again
    (pure {i1 :: i2 :: nil}))))) ; return the two intermediate internal states

(main {(runState stateInteger 42) & show & println})

This should demo this new functionality for random:

(def example-of-the-draw-functions : (State PRNG (List Double))
  (do
    [d0 <- draw-double]
    [d1 <- draw-double]
    (put (prng/seeded 1337))
    [d2 <- draw-double]
    [d3 <- draw-double]
    (put (prng/seeded 1337))
    [d4 <- draw-double]
    [d5 <- draw-double]
    (pure {d0 :: d1 :: d2 :: d3 :: d4 :: d5 :: nil })))

(main
  (do

    ; In IO, get a PRNG seeded by the current time:
    [prng <- make-io-prng]

    (println " First two numbers in the following are different, and different on each run of this program, confirming the IO-seed PRNG is \"proceeding\",")
    (println " and the third and fifth are the same, as as the fourth and sixth, to show the 'put' has reseeded deterministically")

    ; run an example State computation with the prng we just got from IO
  {(runState example-of-the-draw-functions prng) & fst & show & println}

    ; And finally, with a deterministally-seeded PRNG (i.e. not created in IO)
  {(runState example-of-the-draw-functions (prng/seeded 1337)) & fst & show & println}))

@aaronmcdaid
Copy link
Author

By the way, I'm relatively new to working with others on github. I've just realised that maybe I should have sent a pull request to @iitalics instead, as this extends their code. I don't really know the etiquette around these things

@lexi-lambda
Copy link
Owner

In an ideal world, I think the right thing to do here would be to define a StateT transformer, then define a RandomT transformer as a newtype-ish thing around StateT, with a variety of instances derived using something like GeneralizedNewtypeDeriving. However, Hackett has neither newtypes nor GND, so just writing StateT for now seems reasonable. I would put it in hackett/monad/state, however, much like how ErrorT and ReaderT are already defined.

@aaronmcdaid
Copy link
Author

aaronmcdaid commented Nov 13, 2017

I haven't had any time for Hackett in recent weeks, partly because of a C++ conference I attended (Meeting C++ 2017, it was fantastic!). But maybe I will again in a few weeks. I'm going to Nepal on Thursday for three weeks trekking up to 5000m. In future, I may be able to follow up on this, if nobody else does so first. Thanks again for the excellent feedback :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants