2016-04-14 35 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