Why is the transformer the first argument to the start function?

I mean, why is this not the last?

Because of this agreement, to evaluate the transformer stack, you need to write such an inconvenient thing:

runStateT (runReaderT (runRWST stack rs) r') s' 

instead:

 runStateT s' $ runReaderT r' $ runRWST rs $ stack 

And combining it with immediate do is becoming more and more inconvenient:

 let action = do liftIO $ putStrLn "Do" liftIO $ putStrLn "something" in runStateT (runReaderT (runRWST action rs) r') s' 

instead:

 runStateT s' $ runReaderT r' $ runRWST rs $ do liftIO $ putStrLn "Do" liftIO $ putStrLn "something" 

Does this have motivation or is it just a bad agreement?

By the way, I understand that the existing convention simplifies the implementation of the "run" function using the write syntax, but this cannot be an argument, since libraries should prefer usability for ease of implementation.

+8
haskell monad-transformers
source share
3 answers

In the HaskellWiki entry for Parameter Order and this> Question about Stack Overflow, there are two recommendations for parameter order:

In my experience with the Reader / State monad, the same calculation is called in different environments / states more often than different monadic calculations are called in the same environment / state. The current order of parameters is convenient for this.

Another reason: Reader / State monadic values ​​behave very similarly to functions that take the environment / initial state as parameters. And the Haskell functions go up to the parameters.

To avoid the need for nested ReaderT / StateT / RWST , you can work with a single RWST transformer carrying a global state / environment, and use zoom and magnify from lens to adapt calculations that work in more limited environments.

+4
source share

I am sure this makes sense. Very easy to identify

 newtype StateT = StateT { runStateT :: s -> m (a, s) } 

and run with it.

+3
source share

I would like to add a sequence as a response to the mix. These are all assumptions, so take this with salt:

In the initial implementations, the newtype write syntax was used to write these data definitions, so the data is executed the first time it is run, regardless of whether it is preferable for the data coming in as the last argument. Newer data types simply follow this convention.

0
source share

All Articles