transforming IO String to String

℡╲_俬逩灬. 提交于 2019-12-20 07:16:42

问题


I am having an issue converting IO String() to a String() Below is the function to eval an expression.

foobar :: String -> IO String

eval :: String -> Sh () ()
eval x =  do
 s <- foobar x
 shellPutStrLn $ s

This isnt working, because eval returns IO String instead of Sh. The moment some IO is done within a function it transforms/taints it into IO String. How do I prevent the transformation or convert an IO String to String ?


回答1:


It looks like your Sh type is supposed to be able to do IO. The usual way to implement this is with monad transformers. Then you would have:

instance MonadIO Sh where -- definition elided because you don't show Sh

shellPutStrLn :: String -> Sh ()
shellPutStrLn = liftIO . putStrLn

eval :: String -> Sh ()
eval x = do
  s <- liftIO $ foobar x
  shellPutStrLn s

See the MTL for a lot of ready monad transformers you can use, and xmonad for a good example of this style in practice.




回答2:


This "tainting" of your string is deliberate and cannot be avoided without resorting to dirty hacks. You can extract the String temporarily, however, provided you put the result back in IO when you're done. For example

foobar :: String -> IO String

baz :: String -> IO Int
baz str = do
    result <- foobar str
    return (length result)

I would recommend reading up on Haskell IO

  • Real World Haskell: Input and Output.
  • Haskell IO without monads.



回答3:


You can say that you are operating within some monad any time you use the 'do notation'. For example, the code below operates within the IO monad:

printThem x y = do
    print ("x: " ++ show x)
    print ("y: " ++ show y)

You can't mix monads in the same 'do' block. This is what you are attempting here.

eval :: String -> Sh () ()
eval x =  do          -- Which monad? There can be only one!
    s <- foobar x     -- IO monad
    shellPutStrLn $ s -- Sh monad

You will have to execute foobar in an outer layer. Use something like the following. I don't know where your Sh monad is coming from, so I'll just pretend that there is a runShell :: Sh () -> IO () function:

doSomeIO :: IO ()
doSomeIO = do
    s <- foobar x
    runShell $ shellPutStrLn s


来源:https://stackoverflow.com/questions/5948300/transforming-io-string-to-string

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!