我在将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字符串转换为字符串?
答案 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
答案 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