2016-04-14 62 views
1

我正在嘗試編寫一個非常簡單的函數,它需要一個列表(例如:[1,2,3,1,5])並返回緊跟在特定元素之後的元素列表。使用高階函數和Lambda微積分在Haskell中操作列表

我迄今達到是:

function element list = filter (\x -> element:x) list 

我所需的輸出:

函數1 [1,2,3,1,5]

=>   [ 2,5]

+0

通過「旁邊的」,我想你的意思是「後」 ,對嗎?確切地說, – jamshidh

+0

;指定的元素direclty在所需的元素之前 –

+0

w /列表解析這是'foo a xs = [y | (x:y:_)< - tails xs,x == a]'。 ['tails'來自Data.List](https://hackage.haskell.org/package/base-4.8.2.0/docs/Data-List.html#v:tails)。 –

回答

5

試試這個

map snd $ filter ((== x) . fst) $ zip theList (tail theList) 

這不會在空列表上工作,您仍然需要額外的代碼來處理這個問題。


這是如何工作的?

首先,請注意值從右向左流動。 ($)運營商允許這發生。因此,評估的第一部分是zip函數。

zip theList (tail theList) 

對於你上面的例子,這將產生

zip [1,2,3,1,5] [2,3,1,5] 

等於

[(1,2), (2, 3), (3, 1), (1,5)] 

這是一套在列表中同時對。

接下來,過濾器應用

filter ((== x) . fst) $ .... 

在英語中,它說的是,僅過濾出併發對的首元素等於x。輸出是

[(1,2), (1,5)] 

現在我們必須開始併發對的列表。

最後,我們應用地圖

map snd $ .... 

這只是翻出了對的第二值。

map snd [(1,2), (1,5)] = [2,5] 

這是期望值。


請注意,我上面關於在空列表上失敗的評論。

這是因爲tail崩潰空白列表上

tail [] --error 

有辦法來修補這種行爲(見safe包,例如),但它主要是在這一點上記賬,所以我離開了這爲你解決問題。


還要注意,由於所有的,我們使用的功能是懶惰的,這種方法會爲無限長的名單正常工作。

+0

只需用'drop 1'代替'tail',它也可以用於空列表。 –

0

你可以用一個簡單的列表理解這樣做很容易,如:

successors xs i = [y | (x,y) <- zip xs (drop 1 xs), x == i] 
0

這將工作到您的規格

next x (i:y:ys) -- look at the first two items in the list 
    | x == i = -- if the first item == x, 
     y : next x (y:ys) -- take the second, and continue minus the first element 
    |otherwise = -- not equal, 
     next x (y:ys) -- so skip that element 
next _ [_] = [] -- if there's no second element, then stop 
next _ _ = [] -- if the list is empty, stop