【问题标题】:Haskell List Comprehension creating functionHaskell List Comprehension 创建函数
【发布时间】:2013-01-30 01:20:50
【问题描述】:

我是 Haskell 的新手,正在努力学习基础知识。我很难理解如何操作列表的内容。

假设我有以下列表,我想创建一个函数来从列表中的每个元素中减去 1,我可以简单地将 x 传递给函数,这将如何完成?

Prelude>let x = 1:2:3:4:5:[]

类似:

Prelude>subtractOne(x)

【问题讨论】:

  • 你的意思是Prelude> subtractOne x?请记住,Haskell在函数中使用括号。
  • @Code-Guru,subtractOne(x) 的表达是完全合法的,虽然不是 Haskellish
  • @Code-Guru,以 Haskell 自己命名的 Curry 函数怎么样!他们在函数中使用括号并工作 %100 并且是 Haskell 的一部分。
  • @nameless 我不知道。我读过的所有Haskell代码都没有使用括号,所以我没有考虑它是否合法。经过思考,我明白为什么它有效。我怀疑括号只是围绕表达式 x 并且 not 用于函数调用。
  • add (x,y) 中的括号说明了 Haskell 用于提取 2 元组的两个元素的模式匹配功能。

标签: haskell


【解决方案1】:

(您可以将1:2:3:4:5:[] 更简单地写为[1,2,3,4,5] 甚至[1..5]。)

理解

你想使用列表推导,所以这里是:

subtractOne xs = [ x-1 | x <- xs ]

这里我使用xs 代表我要从中减去一个的列表。

首先要注意的是x &lt;- xs,您可以将其解读为“x 取自xs”。这意味着我们将依次获取xs 中的每个号码,并且每次我们都会调用号码x

x-1 是我们为每个x 计算和返回的值。

有关更多示例,这里有一个为每个元素添加一个 [x+1|x&lt;-xs] 或平方每个元素 [x*x|x&lt;-xs]

多个列表

让我们更深入地了解列表推导,编写一个函数,先找到平方数,然后再找到我们给它的数字的立方数,所以

> squaresAndCubes [1..5]
[1,4,9,16,25,1,8,27,64,125]

我们需要

squaresAndCubes xs = [x^p | p <- [2,3], x <- xs]

这意味着我们将p 的幂设为 2 然后 3,并且对于每个幂,我们从 xs 中获取所有 xs,并计算 x 的幂 p (x^p )。

如果我们反过来做会发生什么?

squaresAndCubesTogether xs = = [x^p | x <- xs, p <- [2,3]]

我们得到

> squaresAndCubesTogether [1..5]
[1,1,4,8,9,27,16,64,25,125]

它获取每个x,然后直接给你它的两个权力。

结论 - &lt;- 位的顺序告诉您输出的顺序。

过滤

如果我们只想允许一些答案怎么办?

2到100之间的哪些数字可以写成x^y

> [x^y|x<-[2..100],y<-[2..100],x^y<100]
[4,8,16,32,64,9,27,81,16,64,25,36,49,64,81]

这里我们允许所有x 和所有y,只要x^y&lt;100


因为我们对每个元素都做同样的事情,所以我会在实践中使用map

takeOne xs = map (subtract 1) xs

或更短为

takeOne = map (subtract 1)

(我必须称它为subtract 1,因为- 1 会被解析为负1。)

【讨论】:

    【解决方案2】:

    您可以使用map 函数来做到这一点:

    subtractOne = map (subtract 1)
    

    List Comprehensions 的替代解决方案更加冗长:

    subtractOne xs = [ x - 1 | x <- xs ]
    

    为了清楚起见,您可能还想添加类型注释。

    【讨论】:

    • +1 谢谢!你能解释一下列表理解是如何工作的吗?它是怎么读的?我不太关心解决方案,而更关心学习如何使用列表理解......
    • @MHZ,您可以这样解读:“对于xs 中的每个项目x,评估表达式x - 1,并将每个评估的结果合并到新列表中。”跨度>
    【解决方案3】:

    您可以使用 map 函数轻松完成此操作,但我怀疑您想自己滚动一些东西作为学习练习。在 Haskell 中执行此操作的一种方法是使用递归。这意味着您需要将函数分为两种情况。第一种情况通常是最简单类型输入的基本情况。对于列表,这是一个空列表[]。从空列表的所有元素中减一的结果显然是一个空列表。在 Haskell 中:

    subtractOne [] = []
    

    现在我们需要考虑稍微复杂的递归情况。对于任何列表除了一个空列表,我们可以查看输入列表的头部和尾部。我们将从头部减去一个,然后将subtractOne 应用于列表的其余部分。然后我们需要将结果连接在一起形成一个新列表。在代码中,这看起来像这样:

    subtractOne (x:xs) = (x - 1) : subtractOne xs
    

    正如我之前提到的,您也可以使用map 执行此操作。实际上,它只是一条线,并且是首选的 Haskellism。另一方面,我认为编写自己的函数使用显式递归以了解其工作原理是一个非常好的主意。最终,您甚至可能想编写自己的 map 函数以供进一步练习。

    【讨论】:

    • +1 @Code-Guru 谢谢! Haskell 中递归的很好解释,不管我们的“柯里化函数”差异如何;)
    【解决方案4】:

    map (subtract 1) x 可以工作。

    subtractOne = map (subtract 1) 
    

    map 函数允许您将函数应用于列表的每个元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-01
      • 2017-11-09
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 2023-04-02
      相关资源
      最近更新 更多