我想向此有效因子列表返回None(或者Haskell等效于None),并且每当遇到无效数字(运行该数字不会返回0的数字)时,在与x)一起使用的模数函数中,我想返回None,以便列表仅包含因子。代码中可能存在一些错误,我是Haskell的新手,所以您必须原谅草率的代码等等。
我曾经尝试使用return可能是x,因为我听说它可以工作,但是我没有运气(不过可能使用不正确)。我还考虑过使用某种标准值并使用seoarate函数来过滤掉这些值,但我认为必须有更好的方法。
import Data.List
import System.IO
checkPerfect x
| x == sum factor x = return x
| otherwise = return None
factor x
| mod x [1..x-1] == 0 = return x
| otherwise = return None
main = do
putStrLn "Upper limit?"
limit <- readLn
let uncheckedNumbers = [1..limit]
let perfectNumbersRaw = map checkPerfect uncheckedNumbers
putStrLn ("Perfect numbers: " ++ perfectNumbersRaw)
答案 0 :(得分:10)
通常, Maybe a
类型用于返回可能失败的计算,或者返回 Either String a
,其中Left
构造函数返回错误消息。
请注意,Haskell没有return
声明。 return
是用于monad的函数。严格来说,您可以在此处使用return
将结果包装在Just
构造函数中,但显式地进行读取可能更容易理解。
话虽如此,您的程序在语法和语义上都有很多问题:
x == sum factor x
将不会计算因子/除数的总和,因为factor
将返回一个数字(可能包裹在Maybe
中),是的,您可以计算Num a => Maybe a
类型,但这是它包装的唯一项的总和,如果是0
,则为Nothing
; return
,因为Haskell没有return
语句; show :: Show a => a -> String
将其转换为字符串; map checkPerfect
,您将生成一个列表,其中包含针对每个项目的Just x
或Nothing
,您可能想使用filter
。我认为在这里更有意义的是返回Bool
,然后过滤列表:
checkPerfect :: Integral i => i -> Bool
checkPerfect x = x == sum (filter ((==) 0 . mod x) [1 .. x-1])
或如@melpomene所说的那样理解列表:
checkPerfect :: Integral i => i -> Bool
checkPerfect x = x == sum [ k | k <- [1 .. x-1], mod x k == 0 ]
,然后使用以下命令打印项目列表:
main = do
putStrLn "Upper limit?"
limit <- readLn :: IO Int
putStrLn ("Perfect numbers: " ++ show (filter checkPerfect [1 .. limit]))
如果以10'000为上限,我们将得到:
Prelude> main
Upper limit?
10000
Perfect numbers: [6,28,496,8128]
答案 1 :(得分:4)
Maybe类型是Haskell中的主要可选类型。例如,您可以使用Just x
和Nothing
,也可以使用其Monad return x
和fail "not perfect"
。请注意,return
是monad的函数,它将值从pure(通常是同一函数的Applicative名称)移动到monadic,并且在不需要包装值时不需要。