在Haskell中执行while循环

时间:2010-12-03 09:50:30

标签: haskell recursion

我有一个功能:

isItSimple :: Int -> Bool

它获得了Int并返回Bool。

我需要在[x |中找到第一个数字x< - [ n .. ],isItSimple x]。

这是我的解决方案:

findIt :: Int -> Int
findIt num
       | isItSimple num = num
       | otherwise = findIt (num + 1)

Haskell有没有更好的解决方案?

5 个答案:

答案 0 :(得分:21)

  

我需要在[x |中找到第一个数字x< - [n ..],isItSimple x]。

就像你说的那样。

findIt n = head [ x | x <- [n..], isItSimple x ]

答案 1 :(得分:14)

虽然其他答案有效,但它们可能不是在Haskell中解决这个问题的最常用方法。你真的不需要任何额外的导入:Prelude中的一些函数可以解决这个问题。

首先创建一个大于或等于n的所有简单数字的列表。函数filter :: (a -> Bool) -> [a] -> [a]使这很容易:

filter isItSimple [n..]

[n..]类似,这是一个无限列表,但这不是问题,因为Haskell很懒,在需要之前不会评估任何内容。

为了得到你想要的东西,你可以把这个无限列表的头脑:

findIt :: Int -> Int
findIt n = head $ filter isItSimple [n..]

有些人不喜欢head,因为它是部分功能,并且在给出空列表时会引发异常。我个人不会在此担心,因为我们知道永远不会在空列表中调用它。它让我比fromJust更不舒服,这也是一个部分功能(当给出Nothing时会引发异常)并且在我看来总是一个坏主意。

(谈到个人品味,我写的如下:

findIt = head . filter isItSimple . enumFrom

这是pointfree风格的一个例子,在我看来这可能会令人费解,但在这种情况下非常优雅。)

答案 2 :(得分:6)

在大多数情况下,特别是当您的问题是解决问题的特定情况时,明确的重新解决是不好的。不使用显式递归的问题的可能解决方案之一是:

import Data.List (find)
import Data.Maybe (fromJust)

findIt :: Int -> Int
findIt n = fromJust $ find isItSimple [n..]

答案 3 :(得分:1)

findIt :: Int -> Int
findIt num = head $ dropWhile (not isItSimple) [num..]

我不知道它是否更好。它刚刚出现在我的脑海里。

答案 4 :(得分:1)

另一种方法是使用最小定点组合器(在Data.Function中修复)

findIt = fix (\f x ->  if isItSimple x then x else f (x + 1))

在这种情况下,它看起来有点过度设计,但如果“搜索空间”遵循比x + 1更复杂的规则,这种技术可能非常有用。