2011-05-10 30 views
0

我遇到將IO String()轉換爲字符串()的問題 下面是評估表達式的函數。將IO字符串轉換爲字符串

foobar :: String -> IO String 

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

這是行不通的,因爲eval返回IO String而不是Sh。 時刻某個IO在一個函數內完成,它將其轉換/玷污爲 IO字符串。 如何防止轉換或將IO字符串轉換爲字符串?

+0

你說的IO字符串意味着()?如果你的意思是'IO String()'不是一個有效的類型,也不是'String()'。 – Squidly 2011-05-10 10:09:23

+0

啊這是IO字符串 – icylisper 2011-05-10 10:13:17

+1

你是否想要做類似於http://donsbot.wordpress.com/2010/08/17/practical-haskell/? – tibbe 2011-05-10 10:48:09

回答

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 

MTL了很多,你可以使用現成的單子變壓器,並xmonad這種風格在實踐中的一個很好的例子。

+0

謝謝。這樣可行。我不知道liftIO – icylisper 2011-05-10 10:30:05

+1

很高興聽到它。如果它解決了你的問題,你會考慮接受這個答案嗎? – 2011-05-10 11:30:28

+0

你應該留在monad中 – eouti 2011-05-10 14:04:30

3

這個「污染」你的字符串是故意的,不能避免骯髒的黑客無法避免。但是,您可以暫時提取String,只要您在完成後將結果返回到IO即可。例如

foobar :: String -> IO String 

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

我會建議對Haskell的IO

1

你可以說在任何時候你使用'do notation'的時候你都在使用某個monad。例如,下面的代碼的IO單子內運行:

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

你不能在同一個「做」塊混合單子。這就是你在這裏嘗試的。

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