Вы можете сказать, что работаете в какой-то монаде в любое время, когда используете «do notation». Например, приведенный ниже код работает в монаде ввода-вывода:
printThem x y = do
print ("x: " ++ show x)
print ("y: " ++ show y)
Вы не можете смешивать монады в одном и том же блоке do. Это то, что вы пытаетесь здесь.
eval :: String -> Sh () ()
eval x = do -- Which monad? There can be only one!
s <- foobar x -- IO monad
shellPutStrLn $ s -- Sh monad
Вам придется выполнить foobar
во внешнем слое. Используйте что-то вроде следующего. Я не знаю, откуда исходит ваша Sh
монада, поэтому я просто притворюсь, что есть функция runShell :: Sh () -> IO ()
:
doSomeIO :: IO ()
doSomeIO = do
s <- foobar x
runShell $ shellPutStrLn s