【问题标题】:Manipulating Lists in Haskell using Higher-Order Functions and Lambda Calculus使用高阶函数和 Lambda 演算在 Haskell 中操作列表
【发布时间】:2016-04-14 19:03:16
【问题描述】:

我正在尝试编写一个非常简单的函数,它接受一个列表(例如:[1,2,3,1,5])并返回一个直接位于特定元素之后的元素列表。

到目前为止我所达到的是:

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

我想要的输出:

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

=>   [2,5]

【问题讨论】:

  • “旁边”是指“之后”,对吗?
  • 完全正确;指定元素直接在所需元素之前
  • 带列表理解,这是foo a xs = [y | (x:y:_) <- tails xs, x==a]tails is from Data.List.

标签: list haskell lambda higher-order-functions


【解决方案1】:

试试这个

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 包),但此时主要是记账,所以我把它留给你解决。


还要注意,由于我们使用的所有函数都是惰性的,因此这种方法也适用于无限长的列表。

【讨论】:

  • 只需将tail 替换为drop 1,它也适用于空列表。
【解决方案2】:

您可以通过简单的列表理解很容易地做到这一点,例如:

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

【讨论】:

    【解决方案3】:

    这将符合您的要求

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-02
      • 1970-01-01
      • 2017-04-21
      相关资源
      最近更新 更多