我有一个在Haskell中计算f(n)的函数。 我必须编写一个循环,以便它将开始计算从f(0)到f(n)的值,并且每次都将f(i)的值与某个固定值进行比较。 我是OOP的专家,因此我发现很难以功能的方式思考。 例如,我必须编写类似
的内容while (number < f(i))
i++
我如何在Haskell中写这个?
答案 0 :(得分:1)
这里的标准方法是
例如,
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)
这将返回一个包含第一个值的对,以使条件失败并给定函数的迭代次数。