преобразование строки ввода-вывода в строку - PullRequest
0 голосов
/ 10 мая 2011

У меня проблема с преобразованием IO String () в String () Ниже приведена функция для вычисления выражения.

foobar :: String -> IO String

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

Это не работает, потому что eval возвращает IO String вместо Sh. В тот момент, когда какой-то ввод-вывод выполняется внутри функции, он превращает / портит его в IO String. Как предотвратить преобразование или преобразовать строку ввода-вывода в строку?

Ответы [ 3 ]

6 голосов
/ 10 мая 2011

Похоже, ваш тип Sh должен быть в состоянии сделать IO.Обычный способ реализовать это с помощью монадных трансформаторов.Тогда вы получите:

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

См. MTL для большого количества готовых монадных трансформаторов, которые вы можете использовать, и xmonad для хорошего примера этого стиля впрактика.

3 голосов
/ 10 мая 2011

Это «порча» вашей строки является преднамеренным и его нельзя избежать, не прибегая к грязным хаки.Однако вы можете временно извлечь String, если вы вернете результат обратно в IO, когда закончите.Например,

foobar :: String -> IO String

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

Я бы порекомендовал прочитать о Haskell IO

1 голос
/ 10 мая 2011

Вы можете сказать, что работаете в какой-то монаде в любое время, когда используете «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
...