2013-04-27 84 views
5

我一直在教自己的Haskell一個月左右,今天我正在閱讀第16個問題的解決方案,並提出了一個問題。從列表中刪除第n個元素

這裏是一個鏈接:http://www.haskell.org/haskellwiki/99_questions/Solutions/16

基本上,這個問題是問,使從列表降到每第N個元素的功能。 例如,

*Main> dropEvery "abcdefghik" 3

"abdeghk"

鏈路中第一個解決方案是

dropEvery :: [a] -> Int -> [a] 
dropEvery [] _ = [] 
dropEvery (x:xs) n = dropEvery' (x:xs) n 1 
    where 
     dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1)) 
     dropEvery' [] _ _ = [] 
     divides x y = y `mod` x == 0 

我的問題是,爲什麼dropEvery定義空列表,而dropEvery」能照顧的情況下,空的清單? 我認爲dropEvery [] _ = []可以簡單地刪除,修改其他一些句子,如下所示應該與上面完全一樣,看起來更短。

任何人都可以幫我弄清楚這個嗎?

+1

請注意,該函數的參數順序是「錯誤的」;像這樣的函數通常是'Int-> [a] - > [a]',這對於流水線情況通常更有用。爲什麼他們在這個例子中反過來說,我不知道。 – leftaroundabout 2013-04-28 10:22:34

回答

7

我認爲它們是一樣的,作者可以按照您的建議簡化代碼。對於這個,我嘗試了兩個版本,分別是QuickCheck,它們看起來是一樣的。


import Test.QuickCheck 

dropEvery :: [a] -> Int -> [a] 
dropEvery [] _ = [] 
dropEvery (x:xs) n = dropEvery' (x:xs) n 1 
    where 
     dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1)) 
     dropEvery' [] _ _ = [] 
     divides x y = y `mod` x == 0 

dropEvery2 :: [a] -> Int -> [a] 
dropEvery2 xs n = dropEvery' xs n 1 
    where 
     dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1)) 
     dropEvery' [] _ _ = [] 
     divides x y = y `mod` x == 0 

theyAreSame xs n = (dropEvery xs n) == (dropEvery2 xs n) 
propTheyAreSame xs n = n > 0 ==> theyAreSame xs n 

而且在ghci中,你可以做

*Main> quickCheck propTheyAreSame 
+++ OK, passed 100 tests. 

我也用手

*Main> dropEvery [] 0 
[] 
*Main> dropEvery2 [] 0 
[] 
*Main> dropEvery [] undefined 
[] 
*Main> dropEvery2 [] undefined 
[] 

測試的幾個角落的情況所以他們似乎是相同的。

因此,我們的學習成果:

  1. 快速檢查是非常適合這種東西
  2. 不要小看自己。 :)
+0

謝謝你的回答!我很高興聽到我的猜測是正確的。我不知道Quickcheck。我需要能夠使用GHC來使用它嗎? – Tengu 2013-04-27 17:25:28

+0

@Tengu你不使用GHC?你也可以使用'runghc'或'ghci',但我相信QuickCheck也可以在完全不同的編譯器上工作。你可以谷歌的安裝指南,但由於它是一個非常普通的庫,它應該很容易安裝。 – Tarrasch 2013-04-27 19:00:14

+0

上個月我剛剛開始了Haskell,我從未使用過GHC編譯器。 (實際上,即使我的計算機科學專業的朋友多次向我解釋過,我實際上甚至不知道「編譯器」的意思是什麼,哈哈)我會查找QuickCheck,但我可能沒有準備好這些東西。謝謝您的回答! – Tengu 2013-04-28 03:27:50