Haskell:循环中的递增索引

时间:2014-11-28 17:09:50

标签: loops haskell indexing

我有一个在Haskell中计算f(n)的函数。 我必须编写一个循环,以便它将开始计算从f(0)到f(n)的值,并且每次都将f(i)的值与某个固定值进行比较。 我是OOP的专家,因此我发现很难以功能的方式思考。 例如,我必须编写类似

的内容
while (number < f(i)) 
   i++

我如何在Haskell中写这个?

4 个答案:

答案 0 :(得分:1)

这里的标准方法是

  1. 创建一个包含f(n)的所有值的无限列表。
  2. 搜索此列表,直至找到您所追求的内容。
  3. 例如,

    takeWhile (number <) $ map f [0..]
    

    如果希望在达到“n”后放弃,您可以轻松地将其添加为单独的步骤:

    takeWhile (number <) $ take n $ map f [0..]
    

    或者,

    takeWhile (number <) $ map f [0 .. n]
    

    您可以通过这种方式进行各种其他过滤,分组和处理。但这需要精神上的转变。这有点像编写for循环来搜索表与编写SQL查询之间的区别。把Haskell看作有点像SQL,你通常会看到如何构建你的代码。

答案 1 :(得分:1)

您可以生成i的列表,f i大于您的号码:

[ i | i<-[0..] , f i > number ]

然后,你可以简单地选择第一个,如果你想要的话:

head [ i | i<-[0..] , f i > number ]

通常,命令式编程中的许多惯用循环可以被重新表述为列表推导,或通过map, filter, foldl, foldr表达。在一般情况下,当循环更复杂时,您总是可以利用递归。

请记住,&#34;盲人&#34;从命令式编程到函数式编程的翻译通常会导致非惯用的,难以阅读的代码,因为在相反的方向进行翻译时会出现这种情况。尽管如此,我发现这种翻译总是可行的。

如果您不熟悉函数式编程,我建议您不要通过翻译您对命令式编程的了解来学习它。相反,从一本好书开始(LYAH是一个受欢迎的选择)。

答案 2 :(得分:0)

从功能方法来看,第一件事就是不清楚你的计算结果是什么。你关心f (i)的最终结果吗?也许你关心i本身。没有副作用,一切都有价值。

假设一旦比较失败,我们假设你想要函数f (i)的最终值。您可以使用递归和警卫来模拟自己的while循环!

while :: Int -> Int -> (Int -> Int) -> Int
while start number f
  | val >= number = val
  | otherwise = while (start + 1) number f
    where
      val = f start

答案 3 :(得分:0)

您可以使用until例如

,而不是显式递归
findGreaterThan :: (Int -> Int) -> Int -> Int -> (Int, Int)
findGreaterThan f init max = until (\(v, i) -> v >= max) (\(v, i) -> (f v, i + 1)) (init, 0)

这将返回一个包含第一个值的对,以使条件失败并给定函数的迭代次数。