2012-12-07 67 views
-5

想從列表中選擇第k個元素,可以在調用像這樣哈斯克爾選擇k個元素

selectN 5 aList 

功能和功能我有

selectN :: Int -> a -> a 
selectN 1 (x:_) = x 
selectN [] _  = error "Index out of bounds" 
selectN k (_:xs) 
    | n < 1   = error "Index out of bounds" 
    | otherwise  = selectN xs (n - 1) 
+0

這是什麼問題? – jozefg

+0

我似乎無法弄清楚如何獲得正確的功能。目前有類似 'selectN :: Int - > [a] - >' 'selectN i list =(i)!!列表' 其中引發無法匹配預期類型'[a]',實際類型爲'Int' 在'(!!)'的第一個參數中,即'(i)' – kqualters

+0

沒關係,用selectN :: Int - > [a] - > selectN i list = list !! (i-1) – kqualters

回答

3

好了,所以有幾個問題首先讓你的代碼,讓我們通過問題:

selectN :: Int -> a -> a --You take in a list of a ie [a] and return a. So this is bit off 
selectN 1 (x:_) = x 
selectN [] _  = error "Index out of bounds" -- Fine but not strictly needed 
selectN k (_:xs) 
    | n < 1   = error "Index out of bounds" 
    | otherwise  = selectN xs (n - 1) --You've got the params backwards here. 

所以要解決這個問題,首先一個好的類型簽名:

selectN :: Int -> [a] -> a 

現在的基本情況:

selectN 1 (x:_) = x --I would suggest using 0 not 1. 
        --Most things in Haskell are 0 based. 
selectN n (x:xs) = selectN (n-1) xs 

使作品,沒有有用的錯誤消息,但你能弄清楚如何添加這些回

它也很容易做到這一點。與(!!)其具有

(!!) :: [a]->Int->a 

所以

類型簽名
selectN = flip (!!) 

結賬hoogle這對於這類事情很有用。

1

要選擇列表的第k個元素,只需使用!!。第一個元素是指數0

selectN = (!!) 

ghci> let test = "abracadabra" 
ghci> test !! 0 
ghci> 'a' 
ghci> test !! 9 
ghci> 'r' 

,但要小心的indexOutOfRange異常

ghci> test !! 11 
*** Exception: Prelude.(!!): index too large 

版:使功能安全

它可以寫一個safeSelectN處理錯誤例外並允許程序安全地繼續而不需要任何IO操作。要做到這一點需要進行以下修改

safeSelectN :: Int -> [a] -> [a] 
safeSelectN n xs = if null xs || length xs < n then [] else [xs !! n] 

在這種情況下,通過接收空列表作爲結果來檢測錯誤。

ghci> safeSelectN 3 "" 
[] 
ghci> safeSelectN 0 "" 
[] 
ghci> safeSelectN 3 "abcd" --like this 
['d'] 

因此,當結果正確時,您不會以第k個元素結束,而只會包含僅包含第k個元素的列表。

+0

你有快速的方法來檢查這個並拋出適當的錯誤嗎? – kqualters

+0

爲了適應輸出結果類型需要適當的錯誤。例如,需要將selectN類型更改爲'selectN :: Int - > [a] - > [a]',如果發生錯誤,結果將是一個空列表。查看我的編輯回覆的詳細信息 –