在Haskell中执行while循环

dem*_*mas 4 recursion haskell

我有一个功能:

isItSimple :: Int -> Bool
Run Code Online (Sandbox Code Playgroud)

它获得了Int并返回Bool.

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

这是我的解决方案:

findIt :: Int -> Int
findIt num
       | isItSimple num = num
       | otherwise = findIt (num + 1)
Run Code Online (Sandbox Code Playgroud)

在Haskell中有更好的解决方案吗?

luq*_*qui 21

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

就像你说的那样.

findIt n = head [ x | x <- [n..], isItSimple x ]
Run Code Online (Sandbox Code Playgroud)

  • @FUZxxl我一般不喜欢`fromJust`,但在这种情况下,它与`head`完全相同,我的意思是在`n`之上没有'x`,满足`isItSimple`将产生"bottom".无论如何,我们永远不会评价`head []`或`fromJust Nothing`. (3认同)

Tra*_*own 14

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

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

filter isItSimple [n..]
Run Code Online (Sandbox Code Playgroud)

[n..]这是一个无限的列表,但这不是问题,因为Haskell是懒惰的,并且在需要之前不会评估任何东西.

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

findIt :: Int -> Int
findIt n = head $ filter isItSimple [n..]
Run Code Online (Sandbox Code Playgroud)

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

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

findIt = head . filter isItSimple . enumFrom
Run Code Online (Sandbox Code Playgroud)

这是一个无样式的例子,在我看来这可能会令人费解但在这种情况下非常优雅.)

  • 无论如何,担心`head`或`fromJust`在这种情况下是多余的,因为如果不存在简单的数字,程序将首先进入无限循环.但我同意'fromJust`几乎不是一个好主意; 至少使用`fromMaybe(错误"What?Inconceivable!")`来明确发生了什么. (2认同)
  • @camccann:对,但对我来说,担心更多的是培养更好的编码习惯.如果我强迫自己假装"fromJust"不存在,我想我会编写更好的代码. (2认同)

fiz*_*ruk 6

在大多数情况下,特别是当您的问题是解决问题的特定情况时,明确的再次出现是不好的.在不使用显式递归的情况下,您的问题的一种可能解决方案是:

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

findIt :: Int -> Int
findIt n = fromJust $ find isItSimple [n..]
Run Code Online (Sandbox Code Playgroud)