将IO String转换为String

时间:2011-05-10 09:55:35

标签: haskell types io monads

我在将IO String()转换为String()时遇到问题 下面是评估表达式的函数。

foobar :: String -> IO String

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

这不起作用,因为eval返回IO String而不是Sh。该 当一些IO在一个函数内完成它转换/玷污它 IO字符串。 如何阻止转换或将IO字符串转换为字符串?

3 个答案:

答案 0 :(得分:6)

看起来您的Sh类型应该能够执行IO。实现这一点的通常方法是使用monad变换器。然后你会:

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

有关您可以使用的许多现成的monad变换器,请参阅MTL,并在实践中查看xmonad这个样式的一个很好的示例。

答案 1 :(得分:3)

你的字符串的这种“污点”是故意的,如果不采取肮脏的黑客行为就无法避免。但是,如果您在完成后将结果放回String,则可暂时提取IO。例如

foobar :: String -> IO String

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

我建议阅读Haskell IO

答案 2 :(得分:1)

你可以说,在你使用'do notation'的任何时候你都在一些monad中运行。例如,下面的代码在IO monad中运行:

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

你不能在同一个'do'块中混合使用monad。这就是你在这里尝试的。

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

您必须在外层执行foobar。使用类似下面的内容。我不知道你的Sh monad来自哪里,所以我只是假装有一个runShell :: Sh () -> IO ()函数:

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