
On 10/26/2015 01:03 PM, Oleg wrote:
For this particular example, the answer is easy: If you have the IO monads, you have the Reader monad, and the State/Writer as well. This is just an IORef.
getFileContents :: IO String getFileContents = do ref <- newIORef False withCSV "data.csv" (myReadFile ref) where myReadFile :: IORef Bool -> Handle -> IO String myReadFile ref handle = do header <- readIORef ref -- ask --- OOOPPSss!!! FAIL! Can't ask. case header of False -> return "" True -> hGetLine handle -- skip first line text <- hGetContents handle return text
Not really. You are passing 'ref' into myReadFile by hand here. If you are willing to pass parameters by hand, there is no need in IORef at all; you could just as well pass header directly. Passing extra arguments is precisely what ReaderT liberates you from. I agree that *given a ReaderT* (or implicit params, or your implicit configurations), you can emulate StateT/WriterT using IORefs (but only one way of stacking w.r.t. exceptions). Roman