使用高阶函数和 Lambda 微积分在 Haskell 中操作列表
Manipulating Lists in Haskell using Higher-Order Functions and Lambda Calculus
我正在尝试编写一个非常简单的函数,它接受一个列表(例如:[1,2,3,1,5]
)和 returns 紧接在特定元素之后的元素列表。
到目前为止我达到的是:
function element list = filter (\x -> element:x) list
我想要的输出:
function 1 [1,2,3,1,5]
=> [2,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)]
现在我们有了以 1.
开头的并发对列表
最后,我们应用地图
map snd $ ....
这只是提取了该对的第二个值。
map snd [(1,2), (1,5)] = [2,5]
这是想要的值。
请注意,我上面关于空列表失败的评论。
这是因为 tail
在空列表上崩溃
tail [] --error
有很多方法可以修补此行为(例如,请参阅 safe
包),但此时主要是簿记,所以我把它留给你解决。
另请注意,由于我们使用的所有函数都是惰性函数,因此这种方法也适用于无限长度的列表。
您可以通过简单的列表理解轻松地做到这一点,例如:
successors xs i = [y | (x,y) <- zip xs (drop 1 xs), x == i]
这将符合您的要求
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
我正在尝试编写一个非常简单的函数,它接受一个列表(例如:[1,2,3,1,5]
)和 returns 紧接在特定元素之后的元素列表。
到目前为止我达到的是:
function element list = filter (\x -> element:x) list
我想要的输出:
function 1 [1,2,3,1,5]
=> [2,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)]
现在我们有了以 1.
开头的并发对列表最后,我们应用地图
map snd $ ....
这只是提取了该对的第二个值。
map snd [(1,2), (1,5)] = [2,5]
这是想要的值。
请注意,我上面关于空列表失败的评论。
这是因为 tail
在空列表上崩溃
tail [] --error
有很多方法可以修补此行为(例如,请参阅 safe
包),但此时主要是簿记,所以我把它留给你解决。
另请注意,由于我们使用的所有函数都是惰性函数,因此这种方法也适用于无限长度的列表。
您可以通过简单的列表理解轻松地做到这一点,例如:
successors xs i = [y | (x,y) <- zip xs (drop 1 xs), x == i]
这将符合您的要求
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