Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify RWST environment variables in Haskell?

Tags:

haskell

monads

I'm trying to build my own project upon an existing project called "GLFW-b-Demo".

Its apparently using something called "RWST" to simulate an environment and state:

data Env = Env
    { envEventsChan    :: TQueue Event
    , envWindow        :: !GLFW.Window
    , envGear1         :: !GL.DisplayList
    , envGear2         :: !GL.DisplayList
    , envGear3         :: !GL.DisplayList
    , envPlane         :: !GL.DisplayList
    , envBlobs         :: ![Blob]
    , envZDistClosest  :: !Double
    , envZDistFarthest :: !Double
    }

data State = State
    { stateWindowWidth     :: !Int
    , stateWindowHeight    :: !Int
    , stateXAngle          :: !Double
    , stateYAngle          :: !Double
    , stateZAngle          :: !Double
    , stateGearZAngle      :: !Double
    , stateZDist           :: !Double
    , stateMouseDown       :: !Bool
    , stateDragging        :: !Bool
    , stateDragStartX      :: !Double
    , stateDragStartY      :: !Double
    , stateDragStartXAngle :: !Double
    , stateDragStartYAngle :: !Double
    }

type Demo = RWST Env () State IO

And retrieving something from that environment is easy enough:

blobs <- asks envBlobs

But I also need to be able to modify the value of those "variables". Would I need to move that to the state, to be able to change it's value or can I also modify the contents of the "env" part of things?

like image 331
Zuzu_Typ Avatar asked Oct 30 '25 13:10

Zuzu_Typ


1 Answers

But I also need to be able to modify the value of those "variables". Would I need to move that to the state, to be able to change it's value or can I also modify the contents of the "env" part of things?

It depends on whether you want to modify those env values "locally", in a computation under your control, or you want to modify them for any possible computation that might come afterwards.

In the first case, you can get by by using local:

local :: (r -> r) -> RWST r w s m a -> RWST r w s m a

When the RWST computation we pass to local exits, the values in the environment r will return to their original versions, unmodified by the r -> r function.

But if you want the changes to be "sticky", you'll need to move those values to the state and use functions like put or modify.

An example:

import Control.Monad.IO.Class
import Control.Monad.Trans.RWS.Strict

action :: RWST Int () Char IO ()
action = do
  local succ $ do -- affects only the nested action
    v <- ask 
    liftIO $ print v
  do
    v <- ask 
    liftIO $ print v -- isn't affected by local
  modify succ -- change seen by the following actions
  do
    s <- get 
    liftIO $ print s -- is affected by modify

main :: IO ()
main = do
  (_, _, _) <- runRWST action 0 'a'
  return ()
-- Results:
-- 1
-- 0
-- 'b'
like image 124
danidiaz Avatar answered Nov 01 '25 14:11

danidiaz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!