【问题标题】:Append integer to global list inside function haskell将整数附加到函数haskell内的全局列表
【发布时间】:2014-12-25 13:59:54
【问题描述】:

我将使用一个简单的示例来说明我正在尝试做的事情。

假设我有清单:

nums = []

现在我有了函数:

allNums n = nums.append(n)

所以如果我运行这个函数:

allNums 6

列表 nums 应该有值

[6] 

我知道 nums.append 不起作用,但是什么代码可以代替它。

【问题讨论】:

  • 我已经回滚了那些把它变成一个关于素数和因子的完全不同的问题的编辑。如果您对附加到全局列表的问题得到了满意的答案,并且现在有一个关于素数的新问题,请提出一个新问题。编辑原始问题会使所有现有的 cmets 及其答案看起来格格不入,并让未来的读者感到困惑。

标签: list function haskell append


【解决方案1】:

简单回答:

你不能那样做。 Haskell 是一种纯粹的函数式语言,这意味着:

  • 函数没有任何副作用。
  • 函数在使用相同参数调用时总是返回相同的结果。
  • 函数可能会被调用,也可能不会被调用,但您不必关心这些。如果没有调用,则不需要,但由于该函数没有任何副作用,所以您不会发现。

复杂的答案:

你可以使用 State Monad 来实现一些行为有点像这样的东西,但这可能对你来说还遥不可及。

【讨论】:

  • 另一个答案:MVars。从技术上讲,您可以拥有一个全局可变变量,但没有初学者真正需要此功能,它实际上仅适用于非常具体和复杂的情况,而且在我使用 Haskell 的这些年中,我从未真正需要使用它。
  • 我还是 Haskell 的初学者,我已经看到了一些你可以用一些不安全的东西做的事情,但恕我直言,这通常是一个坏主意,这是有原因的,但是当你用它然后帮我一个忙:隐藏这个事实,所以我不必在意。但我从未听说过MVars。
  • 它们实际上是可变变量,但为了读取或写入它们,您必须使用 IO 操作。它们是非常原始的对象,使用起来很安全,但您必须更多地担心细节。您不必求助于unsafePerformIO(除非您真的知道自己在做什么,否则永远不要使用它),但几乎总是有更好的方法来做到这一点。
【解决方案2】:

我建议使用 无限列表 而不是附加到全局变量。 确实,haskell 是纯函数式的。但它也很懒惰。直到真正需要时才计算数据的每一部分。它也适用于集合。因此,您甚至可以使用基于同一集合的先前元素的元素定义一个集合。 考虑以下代码:

isPrime n = all (\p -> (n `mod` p) /= 0 ) $ takeWhile (\p ->p * p <= n) primes

primes = 2 : ( filter isPrime $ iterate (+1) 3 )

main = putStrLn $ show $ take 100 primes

在定义素数列表时,isPrime 的定义是琐事。它需要一组小于或等于检查数平方根的素数

takeWhile (\p ->p * p <= n) primes

然后它检查数字在除以所有这些数字时是否只有非零余数

all (\p -> (n `mod` p) /= 0 ) 

$ 这里是application operator

接下来使用这个定义,我们从 3 开始取所有数字:

iterate (+1) 3

并从中过滤素数。

filter isPrime 

然后我们只是在它前面加上第一个素数:

primes = 2 : ( ... )

所以primes 变成了一个无限的自引用列表。

你可能会问:为什么我们在前面加上 2 而只是没有从它开始过滤数字,例如:

primes = filter isPrime $ iterate (+1) 2

您可以检查这导致uncomputable expression,因为isPrime 函数至少需要primes 的一个已知成员才能将takeWhile 应用于它。

如您所见,primes 定义明确且不可变,但它可以在逻辑中包含任意数量的元素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 2022-11-29
    • 1970-01-01
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    相关资源
    最近更新 更多