2012-10-29 175 views
0

我試圖創建自己的字符串隨機播放功能:類型錯誤

import System.Random 

-- usage case: my_shuffle "something" "" 

my_shuffle :: [Char] -> [Char] -> [Char] 
my_shuffle [] result = result 
my_shuffle s result = do 
    pos <- randomRIO (1, length s) 
    my_shuffle (remove_char pos) (result ++ (get_char pos)) 

get_char :: [Char] -> Int -> Char 
get_char s pos = s !! (pos - 1) 

remove_char :: [Char] -> Int -> [Char] 
remove_char s pos = take (pos - 1) s ++ drop pos s 

它返回的錯誤信息:

substitution_cipher.hs:8:16: 
    Couldn't match expected type `[t0]' with actual type `IO a0' 
    In the return type of a call of `randomRIO' 
    In a stmt of a 'do' expression: pos <- randomRIO (1, length s) 
    In the expression: 
     do { pos <- randomRIO (1, length s); 
      my_shuffle (remove_char pos) (result ++ (get_char pos)) } 

當我看到它關係到IO,但我不知道如何解決它。

+1

如果你不確定一個類型,它往往是方便省略式簽名,將其加載到GHCI,並做了':T '使哈斯克爾告訴你的類型。然後,您可以將該類型簽名添加到源代碼中。 –

回答

4

首先,您沒有將字符串參數傳遞給remove_charget_char。此外,您需要將get_char的結果轉換爲列表才能使用++。到my_shuffle遞歸調用應該像這樣:

my_shuffle (remove_char s pos) (result ++ [get_char s pos]) 

其次,您需要使用IO單子爲randomIO,所以my_shuffle簽名應該是:

my_shuffle :: [Char] -> [Char] -> IO [Char] 

然後最後你需要使用return在基本情況下(因爲你需要返回IO [Char]):

my_shuffle [] result = return result 

隨着修復AP合股:

import System.Random 

my_shuffle :: [Char] -> [Char] -> IO [Char] 
my_shuffle [] result = return result 
my_shuffle s result = do 
    pos <- randomRIO (1, length s) 
    my_shuffle (remove_char s pos) (result ++ [get_char s pos]) 

get_char :: [Char] -> Int -> Char 
get_char s pos = s !! (pos - 1) 

remove_char :: [Char] -> Int -> [Char] 
remove_char s pos = take (pos - 1) s ++ drop pos s 
+0

非常感謝您的詳細解答。但是我還有另外一個問題:有什麼方法可以從my_shuffle中返回[Char],而不是IO [Char]。我想用結果作爲公共字符串:f a b = a ++ b; f「some」(my_shuffle「some」「」) – demas

+1

@demas:純粹的函數必須爲相同的輸入返回相同的結果,而'my_shuffle'顯然不會,所以它必須在'IO'中表明它是不確定的。要用'f'來使用它,你可以寫'f'一些「<$> my_shuffle」一些「」「'',這將再次在'IO'中。另一種選擇是通過將隨機數發生器作爲輸入來確定它,但是你必須擔心會傳遞這些數據。 – hammar

+0

@demas - 你正在使用'randomRIO'這意味着你必須返回一個'IO [Char]'。 – ErikR