Doing without IORef

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

Doing without IORef

Jinwoo Lee
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.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Doing without IORef

Bugzilla from alfonso.acosta@gmail.com
> 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
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Doing without IORef

Claude Heiland-Allen
In reply to this post by Jinwoo Lee
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
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Doing without IORef

Brandon S Allbery KF8NH
In reply to this post by Jinwoo Lee

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] [hidden email]
system administrator [openafs,heimdal,too many hats] [hidden email]
electrical and computer engineering, carnegie mellon university    KF8NH


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Doing without IORef

Peter Hercek-2
In reply to this post by Jinwoo Lee
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
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Doing without IORef

Jinwoo Lee
In reply to this post by Bugzilla from alfonso.acosta@gmail.com
But I still have to use IORef this way.


On Thu, Apr 3, 2008 at 7:08 PM, Alfonso Acosta <[hidden email]> wrote:
> 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.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: Doing without IORef

Jinwoo Lee
In reply to this post by Peter Hercek-2
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 <[hidden email]> wrote:
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
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Jinwoo Lee
Always remember that you are unique. Just like everyone else.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Doing without IORef

Brandon S Allbery KF8NH
In reply to this post by Jinwoo Lee

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] [hidden email]
system administrator [openafs,heimdal,too many hats] [hidden email]
electrical and computer engineering, carnegie mellon university    KF8NH


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Doing without IORef

Jinwoo Lee
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 <[hidden email]> 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] [hidden email]
system administrator [openafs,heimdal,too many hats] [hidden email]
electrical and computer engineering, carnegie mellon university    KF8NH





--
Jinwoo Lee
Always remember that you are unique. Just like everyone else.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: Doing without IORef

ajb@spamcop.net
In reply to this post by Jinwoo Lee
G'day all.

Quoting Jinwoo Lee <[hidden email]>:

> 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
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: Doing without IORef

Jinwoo Lee
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, <[hidden email]> wrote:
G'day all.


Quoting Jinwoo Lee <[hidden email]>:

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
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Jinwoo Lee
Always remember that you are unique. Just like everyone else.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: Doing without IORef

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.

        <b
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: Doing without IORef

Jinwoo Lee
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 <[hidden email]> wrote:
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.

       <b



--
Jinwoo Lee
Always remember that you are unique. Just like everyone else.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: Doing without IORef

Bryan O'Sullivan
Jinwoo Lee wrote:

> 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?

Yep.  In case you ever want to multithread your program, you might want
to use an MVar instead of an IORef.

        <b
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe