2015-04-08 53 views
0

我一直在Haskell工作一個多星期,所以我正在練習一些可能對某事有用的函數。我想遞歸地比較兩個列表。當第一個列表出現在第二個列表中時,我只想返回列表開始匹配的索引。會從0開始。這裏的指數是什麼,我想執行澄清一個例子:如何找到一個列表作爲另一個列表出現的索引?

subList [1,2,3] [4,4,1,2,3,5,6] 

結果應該是2

我試圖代碼時:

subList :: [a] -> [a] -> a 
subList [] = [] 
subList (x:xs) = x + 1 (subList xs) 
subList xs = [ y:zs | (y,ys) <- select xs, zs <- subList ys] 
     where select []  = [] 
       select (x:xs) = x 

我收到「輸入錯誤」,我無法弄清楚爲什麼我的語法不起作用。有什麼建議麼?

+0

我得到的錯誤,但沒有人說「輸入錯誤」。你確定你粘貼了你的代碼嗎?你有沒有試過用*這個代碼做一個文件,以確保錯誤在這部分? –

回答

2

我們先來看看函數簽名。你想在兩個列表,其內容可以進行比較,以平等和返回,像這樣

subList :: Eq a => [a] -> [a] -> Int 

索引所以現在我們通過圖案的參數匹配。首先,當第二列表爲空,那麼就沒有什麼可以做,所以我們將返回-1作爲錯誤條件

subList _ [] = -1 

然後我們看看遞歸步驟

subList as [email protected](x:xs) 
    | all (uncurry (==)) $ zip as xxs = 0 
    | otherwise      = 1 + subList as xs 

你應該熟悉我使用的guard語法,儘管您可能不熟悉@語法。實質上,這意味着如果我們使用了(x:xs)xxs只是一個子選項。

您可能不熟悉all,uncurry和可能zip因此,讓我詳細說明這些。 zip具有功能簽名zip :: [a] -> [b] -> [(a,b)],因此它需要兩個列表並將它們的元素配對(如果一個列表比另一個長,那麼它會截掉多餘的)。 uncurry很奇怪,所以我們來看看(uncurry (==)),它的簽名是(uncurry (==)) :: Eq a => (a, a) -> Bool,它基本上檢查對中的第一個和第二個元素是否相等。最後,all將遍歷列表並查看每對中的第一個和第二個是否相等,如果情況如此,則返回true。

+0

一個星期後'all','uncurry'和'zip'可能並不那麼明顯(也許你應該使用'zipWith'和一個lambda來代替?) - 但是很好的答案! – Carsten

+0

@CarstenKönig好點,我會對它進行編輯以解釋那個更好,然後 – randomusername

+0

@randomusername謝謝你的解釋,因爲我一直在閱讀「To Learn You Haskell」一書,所以我對'zip'很熟悉。不過謝謝你向我解釋其他人。 – ExecutionStyle21

相關問題