在这种情况下,有效替代“ None”作为空返回值的方法是什么

时间:2019-09-13 19:17:48

标签: haskell

我想向此有效因子列表返回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)

2 个答案:

答案 0 :(得分:10)

通常, Maybe a 类型用于返回可能失败的计算,或者返回 Either String a ,其中Left构造函数返回错误消息。

请注意,Haskell没有return 声明return是用于monad的函数。严格来说,您可以在此处使用return将结果包装在Just构造函数中,但显式地进行读取可能更容易理解。

话虽如此,您的程序在语法和语义上都有很多问题:

  1. 在数论中,理想数是一个正整数,等于其正因数之和,不包括数字本身。[wiki],不是因数。
  2. x == sum factor x将不会计算因子/除数的总和,因为factor将返回一个数字(可能包裹在Maybe中),是的,您可以计算Num a => Maybe a类型,但这是它包装的唯一项的总和,如果是0,则为Nothing
  3. 如前所述,您可能一开始不应该使用return,因为Haskell没有return 语句;
  4. 您不能在字符串后附加数字列表,但是可以使用show :: Show a => a -> String将其转换为字符串;
  5. 通过使用map checkPerfect,您将生成一个列表,其中包含针对每个项目的Just xNothing,您可能想使用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 xNothing,也可以使用其Monad return xfail "not perfect"。请注意,return是monad的函数,它将值从pure(通常是同一函数的Applicative名称)移动到monadic,并且在不需要包装值时不需要。