2015-02-10 75 views
-1

如何修改下面的函數,使得列表比搜索索引短的情況會導致錯誤。Haskell列表索引超出範圍

elementAt::Int -> [Int] -> Int 
elementAt = Data.Foldable.foldl (\x y -> if x == 0 then y else x-1) 

1是第一元件

+2

即使您嘗試獲取列表範圍內的元素,我認爲這個函數是錯誤的。例如,'elementAt 0 [1,2,3]'將返回'3'。 – WilQu 2015-02-10 10:11:04

+0

我認爲顯式遞歸在這種情況下比褶皺更容易使用。 – chi 2015-02-10 10:20:41

+0

1被認爲是我忘記提及的索引元素,因此0被認爲是越界 – yonutix 2015-02-10 11:17:12

回答

6

的使用摺疊來查找列表中的第n個元素是一個相當困難的方式的索引。我想向您介紹使用顯式遞歸一個簡單的方法:你必須看看這個問題,不同的

  1. 什麼是我的基本情況?
  2. 遞歸調用應該如何?
  3. (可選)錯誤怎麼辦?

方法的類型簽名給出:

只擔心第一點
elementAt :: Int -> [Int] -> Int 

,我們知道,如果索引0,我們要返回元素:

elementAt 1 (x:_) = x 

現在如果我們的號碼大於1呢?在這種情況下,我們希望減少我們的索引結束測試下一項的謂詞:

elementAt n (x:xs) = elementAt (n-1) xs 

現在我們差不多完成了!如果我們想,如果在指定位置的元素沒有找到引發錯誤,我們可以簡單地使用error

elementAt _ _ = error "Element not found!" 

但這不是慣用的Haskell方式是如何工作的。一個可能的解決方案是使用一個Maybe包裹的結果對於這一點,我們必須改變類型簽名一點點:

elementAt :: Int -> [Int] -> Maybe Int 

現在的功能是能夠以如果指定的位置返回Just元素存在和Nothing否則:

elementAt 1 (x:_) = Just x 
elementAt n (x:xs) = elementAt (n-1) xs 
elementAt _ _  = Nothing 

爲了完整起見,在這裏一個可能的方式實現這一目標,雖然摺疊:

elementAt n = foldl (\acc x -> if fst x == n then snd x else acc) n . zip [1..n] 
+0

似乎是一個很好的答案,我希望有一個更短的方法來做到這一點,謝謝! – yonutix 2015-02-10 11:18:35

+0

@CosminMihai有一個簡短的方法來做到這一點,但我可以向你保證,實現/閱讀並不容易。 – ThreeFx 2015-02-10 11:19:50

+0

如果你知道更好的方法,請分享它 – yonutix 2015-02-10 11:22:12