
Hi, Recently I wrote a code that uses readline library (System.Console.Readline). I had to maintain a state (file path) and do IO throughout the code, so I decided to use StateT monad. The problem was that in order to retrieve the current state (file path) inside the handler that had been registered by using bindKey function of readline, I had to resort back to using IORef rather than using the state stored in the StateT monad. It's because the handler for bindKey should have the type of Int -> Char -> IO Int. Here is my code snippet. type MyState a = StateT FilePath IO a rootDir :: FilePath rootDir = "/root/" main :: IO () main = do hSetBuffering stdout NoBuffering execStateT (do pwd <- get pwdRef <- lift $ newIORef pwd lift $ bindKey '\t' (tabHandler pwdRef) lift $ bindKey '\^L' ctlLHandler commandLoop pwdRef) rootDir return () tabHandler :: IORef FilePath -> Int -> Char -> IO Int tabHandler pwdRef _ _ = do *pwd <- readIORef pwdRef* insertText pwd return 0 ... commandLoop :: IORef FilePath -> MyState () commandLoop pwdRef = commandLoop' where commandLoop' = do pwd <- get *lift $ writeIORef pwdRef pwd* maybeLine <- lift $ readline $ makePrompt $ dropTrailingPathSeparator pwd case maybeLine of Nothing -> return () Just "exit" -> return () Just line -> do let tokens = words line case tokens of [] -> commandLoop' ("exit":_) -> return () _ -> do lift $ addHistory line processLine tokens commandLoop' ... Is there any way in which I can do without IORef in tabHandler and commandLoop (written in red and bold, if you can see)? Thanks, Jinwoo -- Jinwoo Lee Always remember that you are unique. Just like everyone else.

But I still have to use IORef this way.
On Thu, Apr 3, 2008 at 7:08 PM, Alfonso Acosta
type MyState a = StateT FilePath IO a
Is there any way in which I can do without IORef in tabHandler and commandLoop (written in red and bold, if you can see)?
How about keeping the IORef but storing it inside the state?
type MySate a = StateT (IORef FilePath) IO a
-- Jinwoo Lee Always remember that you are unique. Just like everyone else.

On Apr 3, 2008, at 21:07 , Jinwoo Lee wrote:
But I still have to use IORef this way.
You can't escape the IORef unless you can convince the library to thread your state everywhere that it needs to be modified *and* where it needs to be read, without copying it. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

OK. I understand it now. I think the article Claude suggested is worth a read because it shows how to hide using IORef in simple APIs. Thanks, jinwoo On Fri, Apr 4, 2008 at 10:17 AM, Brandon S. Allbery KF8NH < allbery@ece.cmu.edu> wrote:
On Apr 3, 2008, at 21:07 , Jinwoo Lee wrote:
But I still have to use IORef this way.
You can't escape the IORef unless you can convince the library to thread your state everywhere that it needs to be modified *and* where it needs to be read, without copying it.
-- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH
-- Jinwoo Lee Always remember that you are unique. Just like everyone else.

Jinwoo Lee wrote:
Hi,
Recently I wrote a code that uses readline library (System.Console.Readline). I had to maintain a state (file path) and do IO throughout the code, so I decided to use StateT monad.
The problem was that in order to retrieve the current state (file path) inside the handler that had been registered by using bindKey function of readline, I had to resort back to using IORef rather than using the state stored in the StateT monad. It's because the handler for bindKey should have the type of Int -> Char -> IO Int.
[snip]
Is there any way in which I can do without IORef in tabHandler and commandLoop (written in red and bold, if you can see)?
Probably not, but this is worth a read if you want to hide the plumbing behind the scenes a bit: "Monadic tunnelling: the art of threading one monad through another" http://www.haskell.org/pipermail/haskell-cafe/2007-July/028501.html Claude -- http://claudiusmaximus.goto10.org

On Apr 3, 2008, at 6:03 , Jinwoo Lee wrote:
Recently I wrote a code that uses readline library (System.Console.Readline). I had to maintain a state (file path) and do IO throughout the code, so I decided to use StateT monad.
The problem was that in order to retrieve the current state (file path) inside the handler that had been registered by using bindKey function of readline, I had to resort back to using IORef rather than using the state stored in the StateT monad. It's because the handler for bindKey should have the type of Int -> Char -> IO Int.
You can hide the IORef inside the StateT... but this is one of several cases where I *really* wish the callbacks were MonadIO a => ... -> a t. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Jinwoo Lee wrote:
Is there any way in which I can do without IORef in tabHandler and commandLoop (written in red and bold, if you can see)?
You could just always redefine the key binding for \t with a new closure which contains the updated "pwd" value (or the whole state if you like it more that way). I suppose readline supports key binding redefinition (???). But I do not think I like it more that IORef, I rather use IORefs with imperative interfaces :-) Peter.

Thanks everyone!
Now I think using IORef is the most practical way to do this.
And Claude, I will look into the article that you mentioned.
jinwoo
On Fri, Apr 4, 2008 at 3:08 AM, Peter Hercek
Jinwoo Lee wrote:
Is there any way in which I can do without IORef in tabHandler and commandLoop (written in red and bold, if you can see)?
You could just always redefine the key binding for \t with a new closure which contains the updated "pwd" value (or the whole state if you like it more that way). I suppose readline supports key binding redefinition (???). But I do not think I like it more that IORef, I rather use IORefs with imperative interfaces :-)
Peter.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Jinwoo Lee Always remember that you are unique. Just like everyone else.

Hi Andrew,
I haven't used ReaderT. What are the advantages when using ReaderT instead
of StateT in this case?
Thanks,
jinwoo
On Fri, Apr 4, 2008 at 2:07 PM,
G'day all.
Quoting Jinwoo Lee
: Thanks everyone!
Now I think using IORef is the most practical way to do this.
Just a suggestion: Store it in a ReaderT instead of a StateT.
Cheers, Andrew Bromage
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Jinwoo Lee Always remember that you are unique. Just like everyone else.

Jinwoo Lee wrote:
I haven't used ReaderT. What are the advantages when using ReaderT instead of StateT in this case?
A StateT lets you replace one IORef with another, since it gives you mutable state. A ReaderT gives you *immutable* state, so the type system guarantees that you'll always be using the same IORef.

Thanks Bryan,
To summarize, embed IORef inside ReaderT and use that IORef to read/change
the file path info, both in IO monad and MyState monad. Is this right?
Thank you all!
jinwoo
On Sat, Apr 5, 2008 at 1:56 AM, Bryan O'Sullivan
Jinwoo Lee wrote:
I haven't used ReaderT. What are the advantages when using ReaderT instead of StateT in this case?
A StateT lets you replace one IORef with another, since it gives you mutable state. A ReaderT gives you *immutable* state, so the type system guarantees that you'll always be using the same IORef.
-- Jinwoo Lee Always remember that you are unique. Just like everyone else.
participants (7)
-
ajb@spamcop.net
-
Alfonso Acosta
-
Brandon S. Allbery KF8NH
-
Bryan O'Sullivan
-
Claude Heiland-Allen
-
Jinwoo Lee
-
Peter Hercek