2011-09-26 13 views
2

我已經在Haskell中編寫了一個合併排序,它在使用數字而不是單詞時起作用,我認爲它會。在使用文字和字母時,我只會得到「不在範圍內」。我究竟做錯了什麼?Haskell - 合併排序,整理單詞和數字

這裏是我的代碼:

merge :: Ord a => [a] -> [a] -> [a] 
merge [] ys = ys 
merge xs [] = xs 
merge (x:xs) (y:ys) 
    | x <= y = x : merge xs (y:ys) 
    | otherwise = y : merge (x:xs) ys 

mergeSort :: Ord a => [a] -> [a] 
mergeSort [] = [] 
mergeSort [x] = [x] 
mergeSort xs 
    = merge (mergeSort top) (mergeSort bottom) 
    where 
    (top, bottom) = splitAt (length xs `div` 2) xs 
+1

這適用於Strings,fe 'mergeSort [「香蕉」,「糖果」,「蘋果」]' –

+3

你的代碼看起來沒問題。查看確切的輸入和完整的錯誤信息可能會有幫助。這並不完全有用,因爲* something *不在範圍內...... – fuz

回答

4

你進入你的話也是這樣嗎?

[this,is,an,example,sentence] 

語法不正確。如果你想輸入一個字符串,你必須encapsulte它在雙引號("):

["this","is","an","example","sentence"] 

如果這不是你的錯誤,隨意忽略這個答案。

+0

可以肯定,語法是正確的,這就是爲什麼他得到「不在範圍內」的錯誤,而不是語法錯誤。 – Ingo

+1

@Ingo語法當然是正確的,但它不是OP所要的。 – fuz

3

您的代碼正常工作。

但是,我建議分割列表在一次通過,而不使用length。當然,這裏的順序並不重要,只是我們有兩個大小相同的列表。你可以這樣做的:

splitList [] = ([],[]) 
splitList [x] = ([x],[]) 
splitList (x:y:zs) = let (xs,ys) = splitList zs in (x:xs, y:ys) 

...或尾遞歸...

splitList zs = go zs [] [] where 
    go [] xs ys = (xs, ys) 
    go [x] xs ys = (x:xs, ys) 
    go (x:y:zs) xs ys = go zs (x:xs) (y:ys)  

...或者使用索引...

splitList xs = (go even, go odd) where 
    go f = map snd $ filter (f.fst) $ indexed 
    indexed = zip [0..] xs 

...或使用摺疊...

import Data.List 

splitList zs = snd $ foldl' go (True,([],[])) zs where 
    go (True,(xs,ys)) x = (False,(x:xs,ys)) 
    go (False,(xs,ys)) x = (True,(xs,x:ys)) 
+0

正如我在#haskell上向我指出的那樣,當我提出類似的解決方案時,存在一個折衷:使用此解決方案,排序不穩定。 –

+0

那麼,一次計算原始列表的長度。然後傳遞你發給助手的名單的長度,這可以通過簡單的除法操作完成。我個人認爲,將原始列表中的每個元素映射到單例列表的方法都很酷。 –