Hi,<br><br>Recently I wrote a code that uses readline library (System.Console.Readline).<br>I had to maintain a state (file path) and do IO throughout the code, so I decided to use StateT monad.<br><br>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.<br>
<br>Here is my code snippet.<br><br><br><span style="font-family: courier new,monospace;">type MyState a = StateT FilePath IO a</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">rootDir :: FilePath</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">rootDir = "/root/"</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">main :: IO ()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">main = do hSetBuffering stdout NoBuffering</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> execStateT (do</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> pwd <- get</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> pwdRef <- lift $ newIORef pwd</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> lift $ bindKey '\t' (tabHandler pwdRef)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> lift $ bindKey '\^L' ctlLHandler</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> commandLoop pwdRef) rootDir</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> return ()</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">tabHandler :: IORef FilePath -> Int -> Char -> IO Int</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">tabHandler pwdRef _ _ = do</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> <b><span style="color: rgb(255, 0, 0);">pwd <- readIORef pwdRef</span></b></span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> insertText pwd</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> return 0</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"><br>...<br><br style="font-family: courier new,monospace;"></span><span style="font-family: courier new,monospace;">commandLoop :: IORef FilePath -> MyState ()</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">commandLoop pwdRef = commandLoop'</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> where</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> commandLoop' = do</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> pwd <- get</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> <b><span style="color: rgb(255, 0, 0);">lift $ writeIORef pwdRef pwd</span></b></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> maybeLine <- lift $ readline $ makePrompt $ dropTrailingPathSeparator pwd</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> case maybeLine of</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> Nothing -> return ()</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> Just "exit" -> return ()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> Just line -> do</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> let tokens = words line</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> case tokens of</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> [] -> commandLoop'</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> ("exit":_) -> return ()<br>
_ -> do lift $ addHistory line<br> processLine tokens<br> commandLoop'<br>...<br><br></span><br>Is there any way in which I can do without IORef in tabHandler and commandLoop (written in red and bold, if you can see)?<br>
<br>Thanks,<br>Jinwoo<br><br><br>-- <br>Jinwoo Lee<br>Always remember that you are unique. Just like everyone else.